Shell παραδοξότητες ανακατεύθυνση εισόδου scripting

ψήφοι
16

Μπορεί κανείς να εξηγήσει αυτή τη συμπεριφορά; Τρέξιμο:

#!/bin/sh
echo hello world | read var1 var2
echo $var1
echo $var2

αποτελέσματα σε τίποτα να ouput, ενώ:

#!/bin/sh
echo hello world > test.file
read var1 var2 < test.file
echo $var1
echo $var2

παράγει το αναμενόμενο αποτέλεσμα:

hello
world

Δεν θα έπρεπε ο σωλήνας κάνετε σε ένα βήμα ποιο είναι το ανακατεύθυνση σε test.file έκανε στο δεύτερο παράδειγμα; Δοκίμασα τον ίδιο κώδικα με δύο κελύφη παύλα και bash και πήρε την ίδια συμπεριφορά και από τους δύο.

Δημοσιεύθηκε 05/08/2008 στις 20:26
πηγή χρήστη
Σε άλλες γλώσσες...                            


9 απαντήσεις

ψήφοι
11
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2

δεν παράγει έξοδο λόγω αγωγών τρέχει κάθε ένα από τα συστατικά τους μέσα σε ένα υποφλοιό. Subshells κληρονομούν τα αντίγραφα των μεταβλητών της μητρικής φλοιού, αντί να μοιράζονται τους. Δοκιμάστε αυτό:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
(
    echo $foo
    foo="foo contents modified"
    echo $foo
)
echo $foo

Οι παρενθέσεις ορίζουν μια περιοχή του κώδικα που τρέχει σε ένα υποφλοιό, και $ foo διατηρεί την αρχική του αξία, αφού τροποποιηθεί μέσα τους.

Τώρα δοκιμάστε το εξής:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
{
    echo $foo
    foo="foo contents modified"
    echo $foo
}
echo $foo

Τα σιδεράκια είναι καθαρά για την ομαδοποίηση, δεν υποφλοιό δημιουργείται, και το foo $ τροποποιηθεί μέσα στα άγκιστρα είναι το ίδιο $ foo τροποποιημένο έξω από αυτούς.

Τώρα δοκιμάστε το εξής:

#!/bin/sh
echo "hello world" | {
    read var1 var2
    echo $var1
    echo $var2
}
echo $var1
echo $var2

Μέσα από τις τιράντες, η ανάγνωση ενσωματωμένες δημιουργεί $ var1 και $ var2 σωστά και μπορείτε να δείτε ότι παίρνουν απήχηση. Έξω από τις τιράντες, δεν υπάρχουν πια. Όλος ο κώδικας βρίσκεται μέσα στις αγκύλες έχει τρέξει σε ένα υποφλοιό γιατί είναι ένα συστατικό ενός αγωγού .

Μπορείτε να βάλετε αυθαίρετες ποσότητες κώδικα μεταξύ τιράντες, ώστε να μπορείτε να χρησιμοποιήσετε αυτή την κατασκευή σωληνώσεων-σε-ένα μπλοκ κάθε φορά που χρειάζεστε για να εκτελέσετε ένα μπλοκ του σεναρίου φλοιού που αναλύει την έξοδο από κάτι άλλο.

Απαντήθηκε 19/09/2008 στις 03:20
πηγή χρήστη

ψήφοι
9

Αυτό έχει ήδη απαντηθεί σωστά, αλλά η λύση δεν έχει δηλώσει ακόμα. Χρησιμοποιήστε ksh, δεν bash. Συγκρίνω:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | bash -s

Προς το:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | ksh -s
hello
world

ksh είναι ένα ανώτερο κέλυφος προγραμματισμού λόγω του μικρού του λεπτότητα σαν αυτό. (Bash είναι το καλύτερο διαδραστικό κέλυφος, κατά τη γνώμη μου.)

Απαντήθηκε 15/08/2008 στις 16:52
πηγή χρήστη

ψήφοι
8

Μια πρόσφατη προσθήκη bashείναι η lastpipeεπιλογή, η οποία επιτρέπει την τελευταία εντολή σε έναν αγωγό για να τρέξει στο τρέχον κέλυφος, όχι ένα υποφλοιό, όταν ο έλεγχος δουλειά είναι απενεργοποιημένη.

#!/bin/bash
set +m      # Deactiveate job control
shopt -s lastpipe
echo "hello world" | read var1 var2
echo $var1
echo $var2

πράγματι θα εξόδου

hello
world
Απαντήθηκε 26/07/2012 στις 13:10
πηγή χρήστη

ψήφοι
8
read var1 var2 < <(echo "hello world")
Απαντήθηκε 17/09/2008 στις 01:17
πηγή χρήστη

ψήφοι
5

Εντάξει, εγώ το κατάλαβα!

Αυτό είναι ένα σκληρό bug για να πιάσει, αλλά τα αποτελέσματα από τον τρόπο σωλήνες χειρίζεται από το κέλυφος. Κάθε στοιχείο του αγωγού τρέχει σε μια ξεχωριστή διαδικασία. Όταν τα σύνολα εντολών ανάγνωσης VAR1 και var2, είναι να θέτει τα δικά υποφλοιό αυτό της, δεν τη μητρική κέλυφος. Έτσι, όταν οι έξοδοι υποφλοιό, οι τιμές των var1 και var2 χαθεί. Μπορείτε, ωστόσο, δοκιμάστε να κάνετε

var1=$(echo "Hello")
echo var1

η οποία επιστρέφει την αναμενόμενη απάντηση. Δυστυχώς, αυτό λειτουργεί μόνο για επιμέρους μεταβλητές, δεν μπορείτε να ορίσετε πολλά σε έναν χρόνο. Για να ορίσετε πολλαπλές μεταβλητές σε μια στιγμή θα πρέπει είτε να διαβάσετε σε μια μεταβλητή και το κόβουμε σε πολλαπλά μεταβλητές ή χρησιμοποιήστε κάτι σαν αυτό:

set -- $(echo "Hello World")
var1="$1" var2="$2"
echo $var1
echo $var2

Αν και ομολογώ ότι δεν είναι τόσο κομψό όπως χρησιμοποιώντας ένα σωλήνα, λειτουργεί. Φυσικά θα πρέπει να έχετε κατά νου ότι διαβάζουν έμελλε να διαβάσετε από αρχεία σε μεταβλητές, καθιστώντας έτσι το διαβάσετε από το standard input πρέπει να είναι λίγο πιο δύσκολο.

Απαντήθηκε 05/08/2008 στις 21:09
πηγή χρήστη

ψήφοι
4

να μου σχετικά με το θέμα αυτό (με το Bash):

read var1 var2 <<< "hello world"
echo $var1 $var2
Απαντήθηκε 04/03/2009 στις 10:52
πηγή χρήστη

ψήφοι
4

Η ανάρτηση έχει σωστή απάντηση, αλλά θα ήθελα να προσφέρει μια εναλλακτική λύση μια επένδυση που ίσως θα μπορούσε να είναι κάποια χρησιμότητα.

Για την ανάθεση τιμών διαχωρισμένων χώρο από ηχώ (ή stdout για εκείνο το θέμα) να πληρώνω τις μεταβλητές, θα μπορούσε να εξετάσει τη χρήση συστοιχιών κέλυφος:

$ var=( $( echo 'hello world' ) )
$ echo ${var[0]}
hello
$ echo ${var[1]}
world

Σε αυτό το παράδειγμα var είναι ένας πίνακας και τα περιεχόμενα μπορεί να προσεγγιστεί με τη χρήση του κατασκευάσματος $ {var [index]}, όπου ο δείκτης είναι ο δείκτης array (ξεκινά με 0).

Με αυτόν τον τρόπο μπορείτε να έχετε πολλές παραμέτρους όπως θέλετε ανατεθεί το σχετικό δείκτη πίνακα.

Απαντήθηκε 14/09/2008 στις 18:00
πηγή χρήστη

ψήφοι
4

Είναι επειδή η έκδοση σωλήνα δημιουργεί ένα υποφλοιό, η οποία έχει την μεταβλητή σε τοπικό χώρο της, η οποία στη συνέχεια καταστρέφεται όταν τις εξόδους υποφλοιό.

Εκτελέστε την εντολή αυτή

$ echo $$;cat | read a
10637

και τη χρήση pstree-p για να δείτε τις τρέχουσες διεργασίες, θα δείτε ένα επιπλέον κέλυφος κρέμεται από του κύριου κελύφους σας.

    |                       |-bash(10637)-+-bash(10786)
    |                       |             `-cat(10785)
Απαντήθηκε 05/08/2008 στις 21:00
πηγή χρήστη

ψήφοι
3

Προσπαθήστε:

echo "hello world" | (read var1 var2 ; echo $var1 ; echo $var2 )

Το πρόβλημα, όπως πολλά άτομα έχουν δηλώσει, είναι ότι var1 και var2 δημιουργούνται σε ένα περιβάλλον υποφλοιό που καταστρέφεται όταν αυτό το εξόδους υποφλοιό. Οι παραπάνω αποφεύγει την καταστροφή του υποφλοιό μέχρις ότου το αποτέλεσμα έχει echo'd. Μια άλλη λύση είναι:

result=`echo "hello world"`
read var1 var2 <<EOF
$result
EOF
echo $var1
echo $var2
Απαντήθηκε 17/09/2008 στις 03:15
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more