Διεργασίες

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// σε περιβάλλον λίστας διασπά την έξοδο σε γραμμές