מצב מטפל קובץ והדפסה#
שבעה משתנים שמניעים את ה־I/O של Perl. הם גלובליים - קביעת $/ בשגרה אחת משנה כיצד כל שגרה אחרת באותו תהליך קוראת ממטפל קובץ. המשמעת שמונעת מכך להיות אסון היא ביצוע local: כל שינוי במשתנה בעמוד זה צריך להיות בתוך בלוק local אלא אם התוכנית באמת רוצה שהערך החדש יהיה קבוע.
משתנה | נקרא | ברירת מחדל | משמש את |
|---|---|---|---|
| מפריד רשומת קלט |
|
|
| מפריד רשומת פלט |
|
|
| מפריד שדה פלט |
|
|
| מפריד רשימה |
| שיבוץ מערך |
`$ | ` | autoflush פלט |
|
| מספר השורה הנוכחי |
| מטפל הקובץ האחרון שנקרא |
| מפריד מנויים |
| אמולציית רב־ממדיות |
$/ - מפריד רשומת הקלט#
שולט במה ש־<$fh> ו־readline מתייחסים אליו כסוף רשומה אחת. ברירת המחדל "\n" משמעותה קריאה שורה־אחר־שורה; קביעתו לערכים אחרים מפיקה מצבי קריאה אחרים.
מצב שורה (ברירת המחדל)#
while (my $line = <$fh>) {
chomp $line; # strips the terminator $/
process($line);
}
chomp מסיר את כל מה ש־$/ מחזיק כרגע - כשאתם משנים את $/, chomp עוקב אחריו.
מצב slurp#
undef $/ גורם ל־<> לקרוא את הקובץ כולו בבת אחת:
my $whole_file = do {
local $/;
<$fh>;
};
ה־local חיוני. בלעדיו, כל חתיכת קוד אחרת שקוראת לאחר מכן ממטפל קובץ באותו תהליך תבצע slurp בשקט.
מצב פסקה#
local $/ = ""; קורא פסקה־בכל־פעם, ומפצל על רצפים של שתי שורות חדשות או יותר:
{
local $/ = "";
while (my $para = <$fh>) {
# $para ends with exactly two newlines (or one at EOF)
process_paragraph($para);
}
}
זוהי התנהגות ה־RS="" של awk. שורות ריקות מובילות בתחילת הקובץ מדולגות בשקט.
מצב רשומה־קבועה#
local $/ = \N קורא N בתים בכל קריאה:
local $/ = \4096; # binary 4-KiB chunks
while (defined(my $chunk = <$fh>)) {
process($chunk);
}
ההפניה היא למספר, לא למספר עצמו. זוהי הצורה הנכונה לקריאת נתונים בינאריים, מנות רשת, או ביצוע העתקה בכמות מבלי לסרוק עבור \n.
מסיימים רב־תוויים#
local $/ = "\r\n"; # CRLF mode
local $/ = "\nEND-OF-RECORD\n"; # custom marker
המסיים הוא מחרוזת מילולית, לא regex.
$\ - מפריד רשומת הפלט#
מצורף לכל קריאת print. ברירת המחדל היא undef (לא מצורף דבר). קביעתו משנה כל print הבא:
{
local $\ = "\n"; # all prints get a trailing newline
print "first";
print "second";
}
# Output: "first\nsecond\n"
זוהי ההתאמה הטבעית עבור -l בשורת הפקודה - -l קובע את $\ ל־\n. בקוד סקריפט, local $\ = "\n" בתוך לולאת דיווח צפופה שווה לעיתים; אחרת say (שכופה \n ללא קשר ל־$\) הוא הכתיב הנקי יותר.
$, - מפריד שדה הפלט#
מוכנס בין הארגומנטים של print. ברירת המחדל היא undef:
print "a", "b", "c"; # "abc"
{
local $, = ", ";
print "a", "b", "c"; # "a, b, c"
}
{
local $, = "\t";
print @items; # tab-separated record
}
$, הוא לכל־print, לא לכל־שורה - הוא אינו מפריד בין קריאות print עוקבות. שלבו עם $\ עבור פלט מלא בסגנון TSV:
local ($,, $\) = ("\t", "\n");
print 'col1', 'col2', 'col3'; # "col1\tcol2\tcol3\n"
$" - מפריד הרשימה#
מאחד אלמנטים של מערך כאשר מערך משובץ לתוך מחרוזת במרכאות כפולות. ברירת המחדל היא " " (רווח יחיד):
my @arr = (1, 2, 3);
print "items: @arr\n"; # "items: 1 2 3"
{
local $" = ', ';
print "items: @arr\n"; # "items: 1, 2, 3"
}
{
local $" = "\n ";
print "items:\n @arr\n"; # "items:\n 1\n 2\n 3"
}
$" רק מתייעצים בו בשיבוץ. print @arr (ללא מרכאות) משתמש ב־$,, לא ב־$".
$| - autoflush פלט#
כופה flush לאחר כל כתיבה על מטפל הקובץ הנבחר כרגע:
$| = 1; # autoflush STDOUT
print "Loading..."; sleep 1; # appears immediately, not at exit
הסיוג ”הנבחר כרגע“ חשוב. כברירת מחדל, select מחזיר STDOUT, ולכן $| = 1 מבצע autoflush ל־STDOUT. כדי לבצע autoflush למטפל אחר:
my $old = select($log_fh);
$| = 1;
select($old); # restore selection
הכתיב המודרני הנחמד מעט יותר משתמש ב־IO::Handle:
$log_fh->autoflush(1);
$| נקרא־כבוליאני: print $| מציג 1 או 0.
$. - מספר השורה הנוכחי#
מספר השורה של הקריאה האחרונה בסגנון <>. לכל מטפל קובץ יש מונה משלו; קריאה ממטפל אחר מכנה את $. למונה של אותו מטפל:
while (<$fh>) {
print "$.: $_"; # numbered listing
}
# After the loop, $. is the total number of lines read.
$. מאופס כאשר מטפל הקובץ נסגר. פתיחה מחדש (ללא סגירה מפורשת בינתיים) אינה מאפסת.
עבור איטרציה רב־קבצית דרך <>, השורות ממוספרות באופן מצטבר על פני הקבצים אלא אם תסגרו במפורש את ARGV בכל גבול קובץ - ראו eof עבור הניב התקני close ARGV if eof;.
$; - מפריד המנויים#
משמש לזיוף האשים רב־ממדיים - תכונת מורשת עמוקה שנשמרה לתאימות לאחור:
$h{$x, $y} = $value; # equivalent to $h{"$x\034$y"}
ערך ברירת המחדל הוא "\034" (FS, ”file separator“, בית בקרה ASCII עמום). מבנים רב־ממדיים אמיתיים צריכים להשתמש בהפניות האש מקוננות ($h{$x}{$y}); $; קיים משום של־Perl 4 לא היו הפניות כראוי.
מתי באמת מבצעים local לאלה#
הצורה הנפוצה ביותר, בפער ניכר:
sub slurp_text {
my ($path) = @_;
open my $fh, '<', $path or die "open $path: $!";
local $/; # slurp inside this sub only
return <$fh>;
}
sub paragraphs_of {
my ($path) = @_;
open my $fh, '<', $path or die "open $path: $!";
local $/ = "";
return <$fh>; # list context: list of paragraphs
}
sub csv_print {
my (@row) = @_;
local ($,, $\) = (",", "\n");
print @row;
}
המחיר של שכחת local בלתי־נראה בזמן הכתיבה וקטסטרופלי בזמן השימוש - תת־שגרה ש“רק קובעת $/“ יכולה לשבור קוד לא־קשור שקורא ממטפלי קובץ שונים לחלוטין. התייחסו אל $/, $\, $,, $" כדגלי מצב גלובליים: קבעו אותם תמיד עם local.
ראו גם#
chomp- מסיר את כל מה ש־$/מחזיק כרגע; מזווג עם שינויי$/.eof- הניבclose ARGV if eofשגורם ל־$.לספור לכל־קובץ על פני<>.select- בוחר את מטפל הקובץ שעליו חלים$|וה־$,/$\ללא קידומת.IO::Handle- מספק אתautoflush,output_record_separator, וכו« כקריאות מתודה.local- הדרך הבטוחה לשנות כל משתנה בעמוד זה.שיבוץ - כיצד
$"מעצב הרחבת מערך בתוך מחרוזות במרכאות כפולות.