qx//#
Εκτελεί μια εντολή κελύφους και αποτυπώνει την κανονική έξοδό της.
Η qx// (και το δίδυμό της, η μορφή με backticks `STRING`) παρεμβάλλει τη STRING όπως μια συμβολοσειρά με διπλά εισαγωγικά, παραδίδει το αποτέλεσμα στο κέλυφος του συστήματος, περιμένει να ολοκληρωθεί το παιδί και επιστρέφει ό,τι έγραψε το παιδί στο STDOUT. Η κανονική έξοδος σφάλματος παραμένει ανέπαφη - εξακολουθεί να πηγαίνει στο STDERR του γονέα εκτός αν την ανακατευθύνετε μέσα στην εντολή. Η κατάσταση εξόδου του παιδιού προσγειώνεται στην $?.
Σύνοψη#
my $out = `date`;
my $out = qx/date/;
my @lines = `ls -1 /etc`;
my $raw = qx'echo $HOME'; # single-quote form: no Perl interpolation
Τι επιστρέφεται#
Εξαρτάται από το περιβάλλον:
Βαθμωτό περιβάλλον - μία συμβολοσειρά που περιέχει ολόκληρο το αποτυπωμένο
STDOUT, συμπεριλαμβανομένων όσων ενσωματωμένων newlines υπάρχουν.undefαν δεν μπόρεσε να ξεκινήσει το κέλυφος ή η εντολή.Περιβάλλον λίστας - λίστα γραμμών, διασπασμένη στην τρέχουσα τιμή της
$/(του διαχωριστή εγγραφών εισόδου, newline εξ ορισμού). Κενή λίστα αν δεν μπόρεσε να ξεκινήσει το κέλυφος ή η εντολή.
Η κατάσταση εξόδου του παιδιού τοποθετείται πάντα στην $?, είτε χρησιμοποιείται η αποτυπωμένη έξοδος είτε όχι. Ένα παιδί που δεν γράφει τίποτα και τερματίζει καθαρά αποδίδει "" σε βαθμωτό περιβάλλον, () σε περιβάλλον λίστας και 0 στην $? - η διάκριση «ξεκίνησε αλλά δεν παρήγαγε έξοδο» από «απέτυχε να ξεκινήσει» απαιτεί έλεγχο της $? έναντι του -1 ή της $!.
Καθολική κατάσταση που επηρεάζει#
$?- τίθεται στην κατάσταση αναμονής του παιδιού (στιλwaitpid) σε κάθε κλήση. Το-1σημαίνει ότι το παιδί δεν μπόρεσε να ξεκινήσει, οπότε η$!κρατά τον λόγο.$!- τίθεται όταν το κέλυφος ή η εντολή απέτυχαν να ξεκινήσουν.$/- διέπει το πώς διασπάται σε γραμμές η έξοδος σε περιβάλλον λίστας.$|- επηρεάζει αν η ενταμιευμένη έξοδος της Perl φτάνει στο περιβάλλον του παιδιού πριν τρέξει το παιδί· ορίστε την σε handles εξόδου πριν απόqx//αν έχει σημασία η σειρά με προηγούμενεςprint.%ENV- εξάγεται στο παιδί ως το περιβάλλον του.Ο τρέχων κατάλογος εργασίας, το umask και οι ανοιχτοί περιγραφείς αρχείων κληρονομούνται από το παιδί.
Παραδείγματα#
Αποτύπωση μίας γραμμής:
my $today = `date`;
chomp $today;
print "today is $today\n";
Αποτύπωση γραμμή-γραμμή σε περιβάλλον λίστας:
my @users = `who`;
for my $line (@users) {
my ($name) = split /\s+/, $line;
print "logged in: $name\n";
}
Η παρεμβολή συμβαίνει προτού το κέλυφος δει τη συμβολοσειρά - οι μεταβλητές Perl επεκτείνονται πρώτα, οι μεταβλητές κελύφους επεκτείνονται στο παιδί:
my $dir = "/etc";
my $out = `ls $dir`; # Perl interpolates $dir
my $sh = qx'echo $HOME'; # single-quote form: $HOME is shell's
Ανακατεύθυνση του STDERR στην αποτυπωμένη ροή:
my $both = `gcc -v hello.c 2>&1`;
Απόρριψη του STDERR, διατήρηση μόνο του STDOUT:
my $out = `find / -name core 2>/dev/null`;
Έλεγχος της κατάστασης εξόδου:
my $out = `make test`;
if ($? == -1) {
die "failed to execute make: $!";
}
elsif ($? & 127) {
die sprintf "make died with signal %d", $? & 127;
}
elsif ($? >> 8) {
die sprintf "make exited with status %d", $? >> 8;
}
Οριακές περιπτώσεις#
Κανείς μετα-χαρακτήρας κελύφους: αν η
STRINGδεν περιέχει μετα-χαρακτήρες κελύφους, η Perl παρακάμπτει το κέλυφος και κάνειexecτην εντολή απευθείας - ίδια βελτιστοποίηση με τηνsystem. Αυτό είναι ταχύτερο και αποφεύγει ένα επίπεδοsh -cπαραθέσεων.Οριοθέτης μονού εισαγωγικού: η
qx'...'καταστέλλει την παρεμβολή διπλών εισαγωγικών της Perl. Το κυριολεκτικό$varπερνά στο κέλυφος, το οποίο κάνει τη δική του επέκταση. Χρήσιμο όταν τα ονόματα μεταβλητών ανήκουν στο κέλυφος, όχι στο πρόγραμμά σας Perl.Εναλλακτικοί οριοθέτες: η
qx//δέχεται οποιονδήποτε ισορροπημένο ή μη-αλφαριθμητικό οριοθέτη -qx{ls -l},qx(ls -l),qx[ls -l],qx!ls -l!. Επιλέξτε έναν που δεν συγκρούεται με τη σύνταξη κελύφους στην εντολή σας. ΗqXfooXείναι συντακτικό σφάλμα - ο οριοθέτης δεν επιτρέπεται να είναι αλφαριθμητικός.Τα backticks δεν αποτυπώνουν το STDERR: τίποτα γραμμένο στο
STDERRτου παιδιού δεν καταλήγει στην επιστρεφόμενη συμβολοσειρά. Ανακατευθύνετε με2>&1μέσα στην εντολή αν το θέλετε, ή τρέξτε την εντολή μέσω τηςopenμε σωλήνα για πιο λεπτό έλεγχο.Το STDIN κληρονομείται: το παιδί διαβάζει από ό,τι είχε η διεργασία Perl στο
STDINτη στιγμή της κλήσης. Για να τροφοδοτήσετε στο παιδί συγκεκριμένη είσοδο, χρησιμοποιήστε αντί αυτής τηνopenσε κατάσταση σωλήνα.Κατάσταση εξόδου έναντι
$!: μη μηδενική$?σημαίνει ότι το παιδί έτρεξε και τερμάτισε με σφάλμα· η$!έχει νόημα μόνο όταν η$?είναι-1(δεν μπόρεσε να ξεκινήσει το ίδιο το κέλυφος).Κόστος μνήμης σε βαθμωτό περιβάλλον: ολόκληρη η αποτυπωμένη έξοδος εντάμιεύεται στη μνήμη πριν επιστραφεί. Για εντολές που παράγουν πολύ μεγάλη ή χωρίς όρια έξοδο, ανοίξτε σωλήνα με
openκαι διαβάστε τη σταδιακά.Μορφή συνάρτησης: η
qx//μπορεί επίσης να γραφτεί ωςreadpipeόταν θέλετε σύνταξη κλήσης συνάρτησης - χρήσιμο όταν η συμβολοσειρά εντολής χτίζεται δυναμικά και προτιμάτε να την περάσετε ως βαθμωτό αντί να τη συναρμολογήσετε σε quote-like.Ενταμίευση εξόδου: η Perl εκκενώνει τα ενταμιευμένα handles εξόδου της πριν κάνει fork το παιδί, αλλά η φορητότητα ποικίλλει. Όταν προηγείται
printσε σωλήνα ή αρχείο πριν απόqx//, ορίστε την$|σε εκείνο το handle ώστε να είστε βέβαιοι ότι η έξοδός σας φτάνει στον προορισμό πριν ξεκινήσει το παιδί.Επιλογή κελύφους: το κέλυφος που χρησιμοποιείται είναι το
/bin/shσε Unix. Εντολές που στηρίζονται σε ιδιαιτερότητες του bash χρειάζονται ρητό περιτύλιγμαbash -c '...'.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
system- εκτελεί εντολή κελύφους χωρίς να αποτυπώνει την έξοδο· καταφύγετε σε αυτήν όταν σας ενδιαφέρει μόνο η κατάσταση εξόδουexec- αντικαθιστά την τρέχουσα διεργασία με μια εντολή· καμία αποτύπωση, καμία επιστροφήreadpipe- η ονομασμένη μορφή συνάρτησης τηςqx//· δέχεται την εντολή ως κανονικό όρισμα συμβολοσειράςopen- κατάσταση σωλήνα (open my $fh, "-|", CMD) για ροή της εξόδου ενός παιδιού γραμμή-γραμμή αντί για ενταμίευση ολόκληρης της αποτύπωσης$?- η κατάσταση αναμονής του παιδιού που ορίζει κάθε κλήσηqx//· αποκωδικοποιήστε με>> 8για κωδικό εξόδου και& 127για τερματιστικό σήμα$/- ελέγχει πώς ηqx//σε περιβάλλον λίστας διασπά την έξοδο σε γραμμές