qx//#
מריץ פקודת shell ולוכד את הפלט הסטנדרטי שלה.
qx// (ותאומו, צורת ה־backtick `STRING`) משבץ את STRING כמו מחרוזת בגרשיים כפולים, מעביר את התוצאה ל־shell של המערכת, ממתין לסיום הילד, ומחזיר את כל מה שהילד כתב ל־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שנלכד, כולל כל שורה חדשה מוטמעת.undefאם ה־shell או הפקודה לא יכלו להתחיל.הקשר רשימה - רשימת שורות, מפוצלת על־פי הערך הנוכחי של
$/(מפריד רשומות הקלט, ברירת מחדל שורה חדשה). רשימה ריקה אם ה־shell או הפקודה לא יכלו להתחיל.
סטטוס היציאה של הילד תמיד מושם ב־$?, בין אם הפלט הנלכד בשימוש ובין אם לא. ילד שלא כותב דבר ויוצא נקי מניב "" בהקשר סקלר, () בהקשר רשימה, ו־0 ב־$? - להבחין בין ״התחיל אך לא הפיק פלט״ לבין ״נכשל להתחיל״ דורש בדיקת $? כנגד -1 או $!.
מצב גלובלי שהוא נוגע בו#
$?- נקבע לסטטוס ההמתנה של הילד (בסגנוןwaitpid) בכל קריאה.-1משמעו שהילד לא יכל להתחיל, ובמקרה זה$!מחזיק את הסיבה.$!- נקבע כאשר ה־shell או הפקודה נכשלו להתחיל.$/- שולט בכיצד פלט בהקשר רשימה מפוצל לשורות.$|- משפיע על האם פלט Perl ממוין ב־buffer מגיע לסביבת הילד לפני שהילד רץ; קבעו אותו על מטפלי פלט לפניqx//אם הסדר עםprintקודם חשוב.%ENV- מיוצא לילד כסביבה שלו.ספריית העבודה הנוכחית, ה־umask, וה־file descriptors הפתוחים נרשים על־ידי הילד.
דוגמאות#
לכוד שורה בודדה:
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";
}
שיבוץ מתרחש לפני שה־shell רואה את המחרוזת - משתני Perl מתפרשים תחילה, משתני shell מתפרשים בילד:
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;
}
מקרי קצה#
ללא מטה־תווים של shell: אם
STRINGלא מכיל מטה־תווים של shell, Perl עוקף את ה־shell ומבצעexecישירות לפקודה - אותה אופטימיזציה כמוsystem. זה מהיר יותר ונמנע מרובד אחד של מירכוּבsh -c.מתחם גרש בודד:
qx'...'מדכא את שיבוץ הגרשיים הכפולים של Perl. ה־$varהליטרלי מועבר ל־shell, אשר עושה את ההתפרסות שלו. שימושי כאשר שמות המשתנים שייכים ל־shell, לא לתוכנית Perl שלכם.מתחמים חלופיים:
qx//מקבל כל מתחם מאוזן או לא־אלפאנומרי -qx{ls -l},qx(ls -l),qx[ls -l],qx!ls -l!. בחרו אחד שלא מתנגש עם תחביר shell בפקודה שלכם.qXfooXהוא שגיאת תחביר - המתחם אסור שיהיה אלפאנומרי.backticks אינם לוכדים STDERR: שום דבר שנכתב ל־
STDERRשל הילד לא מגיע למחרוזת המוחזרת. הפנו עם2>&1בתוך הפקודה אם רוצים בכך, או הריצו את הפקודה דרךopenעם pipe לשליטה דקה יותר.STDIN נירש: הילד קורא מכל מה שתהליך Perl החזיק ב־
STDINבעת הקריאה. כדי להאכיל את הילד בקלט ספציפי, השתמשו ב־openבמצב pipe במקום.סטטוס יציאה לעומת
$!:$?שאינו אפס משמעו שהילד רץ ויצא עם שגיאה;$!משמעותי רק כאשר$?הוא-1(ה־shell עצמו לא יכל להיות מופעל).עלות זיכרון בהקשר סקלר: כל הפלט הנלכד מאוחסן ב־buffer בזיכרון לפני שמוחזר. עבור פקודות שמפיקות פלט גדול מאוד או חסר־גבולות, פתחו pipe עם
openוקראו אותו באופן הדרגתי.צורת פונקציה:
qx//יכול להיכתב גםreadpipeכאשר רוצים תחביר של קריאת פונקציה - שימושי כאשר מחרוזת הפקודה נבנית דינמית ועדיף להעביר אותה כסקלר במקום לשבץ אותה לתוך quote-like.Buffering של פלט: Perl עושה flush למטפלי הפלט שלו ה־buffered לפני שהוא עושה fork לילד, אך הניידות משתנה. כאשר מקדימים
qx//עםprintל־pipe או לקובץ, קבעו את$|על אותו מטפל כדי לוודא שהפלט שלכם מגיע ליעד לפני שהילד מתחיל.בחירת shell: ה־shell בשימוש הוא
/bin/shב־Unix. פקודות שמסתמכות על bash-isms זקוקות לעטיפתbash -c '...'מפורשת.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
system- מריץ פקודת shell ללא לכידת פלט; בחרו בו כשמעניין אתכם רק סטטוס היציאהexec- מחליף את התהליך הנוכחי בפקודה; ללא לכידה, ללא החזרהreadpipe- צורת הפונקציה־הנקובה־בשם שלqx//; לוקח את הפקודה כארגומנט מחרוזת רגילopen- מצב pipe (open my $fh, "-|", CMD) להזרמת פלט של ילד שורה אחר שורה במקום ל־buffer את הלכידה כולה$?- סטטוס ההמתנה של הילד שנקבע על־ידי כל קריאתqx//; פענחו עם>> 8עבור קוד יציאה ועם& 127עבור אות סיום$/- שולט בכיצדqx//בהקשר רשימה מפצל פלט לשורות