readline#
קורא רשומה אחת או יותר ממטפל קובץ.
readline הוא פרימיטיב הקלט מאחורי אופרטור היהלום <FH>. הוא קורא ממטפל הקובץ ששמו נקוב ב־EXPR (typeglob, הפניית glob, או IO::Handle), משתמש בערך הנוכחי של $/ כדי להחליט היכן מסתיימת רשומה אחת. אם EXPR הושמט, *ARGV נקרא. בהקשר סקלרי הוא מחזיר את הרשומה הבאה; בהקשר רשימה הוא מחזיר את כל הרשומות הנותרות. סוף־קובץ מסומן על־ידי undef (סקלרי) או רשימה ריקה.
תקציר#
my $line = readline $fh; # one record, scalar context
my @all = readline $fh; # every remaining record
my $line = <$fh>; # same as scalar readline $fh
my @all = <$fh>; # same as list readline $fh
readline; # reads from *ARGV
מה מקבלים בחזרה#
הקשר סקלרי: הרשומה הבאה כמחרוזת, או
undefבסוף־קובץ או בשגיאה. הרשומה כוללת את מסיים השורה שלה ($/הנוכחי) אלא אם לרשומה האחרונה בקובץ חסר אחד. לאחר הערך המוחזר,$.מוגדל - ראו את הסעיף על מצב גלובלי למטה.הקשר רשימה: רשימה של כל הרשומות הנותרות עד סוף־קובץ. רשימה ריקה משמעה שהמטפל כבר היה ב־EOF.
מצב slurp בקובץ ריק: כאשר
$/הואundefוההקשר סקלרי, הקריאה הראשונה על מטפל באפס בייטים מחזירה''(מחרוזת ריקה, מוגדרת); הקריאה הבאה מחזירהundef. זה מאפשר ל־defined($slurp = readline $fh)להבחין בין קובץ ריק לחסר ללא בדיקת-sנפרדת.
מצב גלובלי שהוא נוגע בו#
$/- מפריד רשומת קלט. שולט על מה שנחשב ״רשומה אחת״. ברירת המחדל היא"\n". ערכים מיוחדים מכוסים תחת מצבי רשומה למטה. ידוע גם בשם$INPUT_RECORD_SEPARATORאו$RSתחתuse English.$.- מספר השורה הנוכחי של הקלט מהמטפל האחרון שנקרא.readlineמגדיל את$.פעם אחת לכל רשומה שמוחזרת.$.מאופס כאשר המטפלcloseבמפורש, אך לא כאשר*ARGVמתגלגל מקובץ אחד לבא - זה ממשיך לספור על־פני כל הקלט. גם$INPUT_LINE_NUMBERאו$NRתחתuse English.$_- הסקלר ברירת המחדל. כאשר קריאתreadline(או ה־<FH>המקביל שלה) משמשת כתנאי של לולאתwhileאוfor, Perl משייך באופן מובלע את התוצאה ל־$_ובודקdefined, לא אמת.while (<$fh>) { ... }בטוח לכן בשורות המכילות"0"או"".$!- errno. בשגיאת קריאה,readlineמחזירundef(סקלרי) או רשימה חתוכה, וקובע את$!לשגיאת מערכת ההפעלה.@ARGV- כאשרEXPRהושמט (או שהמטפל הואARGV), כל סוף־קובץ גורם ל־Perl לעשותopenלשם הקובץ הבא מ־@ARGVולהמשיך לקרוא.@ARGVריק גורם ל־ARGVלקרוא אתSTDIN.
מצבי רשומה#
$/ בוחר אחד מארבעה מצבי קריאה:
מצב שורה (ברירת מחדל) -
$/הוא מחרוזת לא־ריקה. רשומה מסתיימת בהופעה הבאה של אותה מחרוזת. עם ברירת המחדל"\n", קריאה אחת מחזירה שורה אחת כולל ירידת השורה שלה.מצב פסקה -
$/ = "". רשומה מסתיימת ברצף הבא של שתי ירידות שורה רצופות או יותר. שורות ריקות מובילות לפני הפסקה הראשונה מדולגות; השורות הריקות המסיימות נכללות במחרוזת המוחזרת. השתמשו ב־local $/ = ""כדי להגביל את השינוי לבלוק.מצב slurp -
$/ = undef. הקריאה הראשונה מחזירה את כל התוכן הנותר של המטפל כמחרוזת אחת; הקריאה הבאה מחזירהundef. בקובץ ריק, ראו את המקרה המיוחד תחת מה מקבלים בחזרה.מצב רשומה־קבועה -
$/ = \N(הפניה למספר שלם חיובי) או$/ = \"N". כל קריאה קוראת בדיוקNבייטים, או פחות בסוף־קובץ. שימושי למסגור בינארי. התוצאה עדיין נספרת כרשומה אחת עבור$..
שינויים ל־$/ נכנסים לתוקף בקריאת ה־readline הבאה. תחמו אותם עם local כך שתת־שגרה לא תשנה בשקט את התפיסה של הקורא לגבי ״שורה״.
דוגמאות#
קריאה אידיומטית שורה־אחר־שורה. תנאי ה־while משייך באופן מובלע ל־$_ ובודק defined:
open my $fh, "<", "input.txt" or die "open: $!";
while (<$fh>) {
chomp;
print "line $.: $_\n";
}
close $fh;
readline מפורש עם זיהוי שגיאות. יש לבדוק את eof בנפרד מערך ההחזרה, מאחר ששורה לגיטימית יכולה להיות המחרוזת הריקה:
while ( ! eof($fh) ) {
defined( my $line = readline $fh )
or die "readline failed: $!";
# ... process $line ...
}
Slurp של קובץ שלם לתוך סקלר:
my $contents = do {
local $/; # undef - slurp mode
open my $fh, "<", $path or die "open $path: $!";
readline $fh;
};
מצב פסקה - קריאת בלוק כותרות הודעה בסגנון RFC-822:
open my $fh, "<", "message.eml" or die $!;
local $/ = "";
my $headers = <$fh>; # up to the first blank line
my $body = do { local $/; <$fh> };
מצב רשומה־קבועה - קריאת בלוקים של 512 בייטים מקובץ התקן:
open my $fh, "<:raw", "/dev/sda" or die $!;
local $/ = \512;
while (defined(my $block = <$fh>)) {
last if length($block) < 512; # short read at EOF
# ... process $block ...
}
הקשר רשימה - למשוך את כל השורות הנותרות בבת אחת. זול עבור קבצים קטנים, הרסני עבור גדולים:
open my $fh, "<", "hosts" or die $!;
my @lines = <$fh>; # every line, including terminators
chomp @lines;
קריאה מ־*ARGV ללא מטפל מפורש - הניב הקלאסי של מסנן Perl. @ARGV נצרך כרשימת שמות קבצים, או STDIN נקרא אם @ARGV ריק:
while (defined(my $line = readline)) {
print $line; # cat(1) in one line
}
מקרי קצה#
EOF מול שגיאה:
readlineסקלרי מחזירundefלשניהם. קראו ל־eof($fh)או בדקו את$!כדי להבחין ביניהם. בתוךwhile (<$fh>)הלולאה יוצאת בכל אחד מהם; הוסיפו בדיקתdefinedמפורשת בתוספת$!כשצריך להבדיל ביניהם.קובץ ללא ירידת שורה נגררת: הרשומה האחרונה מוחזרת ללא מסיים במצב שורה.
chompהוא חסר־פעולה על ערך כזה, וזו ההתנהגות הנכונה.מצב פסקה על קובץ עם שורות ריקות בלבד: מחזיר
undefמיד - אין פסקה לא־ריקה להניב.מצב slurp, קובץ ריק: הקריאה הראשונה מחזירה
''(מוגדרת, באורך אפס); השנייה מחזירהundef. אל תסתעפו על אמיתיוּת הקריאה הראשונה.מצב רשומה־קבועה עם קריאה קצרה ב־EOF: מחזיר את הבייטים הנותרים (אולי פחות מ־
N), ואזundefבקריאה הבאה. בדקוlengthאם אתם צריכים בדיוקN.מטפל הקסם
ARGV: בקריאה מ־*ARGV,eof()ללא ארגומנט מחזיר אמת רק בסוף ממש של כל קבצי@ARGV, בעודeof(ARGV)הוא אמת בסוף כל קובץ. אינכם יכולים להשתמש בניבdefined(readline) or die "...: $!"מול*ARGVלהבחין בין EOF לשגיאה - פתחו כל שם קובץ בעצמכם אם אתם זקוקים לכך.מטפל כבר־סגור:
readlineמחזירundefוקובע את$!ל־"Bad file descriptor". תחתuse warningsאזהרתreadline() on closed filehandleמופקת.שכבות קידוד:
readlineמחזיר את מה שמחסנית ה־PerlIO של המטפל מפיקה. שכבת:utf8או:encoding(...)מפענחת בייטים לתווים; מטפל:rawמחזיר בייטים. ערבוב$/רב־בייטי עם מטפל בייטים יכול לפצל תווים.שינוי
$/באמצע רשומה: רק קריאת ה־readlineהבאה צופה במפריד החדש. כל נתון שכבר עבר buffering נסרק מחדש מולו.<FH>מול<$fh>מול<>: כל אלה הםreadlineמתחת לקלעים.<FH>קורא מה־typeglobFH;<$fh>קורא מהמטפל ב־$fh;<>(או<<>>לטיפול בטוח יותר בשמות קבצים) קורא מ־*ARGV. צורת ה־<pattern>עם כל תוכן אחר היאglob, לאreadline- פונקצייה שונה לחלוטין.השמת תנאי לולאה:
while (my $line = <$fh>) { ... }בודקdefined, לא אמת, רק כי המפענח משכתב אותו.while (($line = <$fh>)) { ... }עם הסוגריים הנוספים אינו מקבל את השכתוב, ויעשה לולאה אינסופית על קלט המכיל"0\n".
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
open- להשגת מטפל הקובץ ש־readlineצורךread- קריאת בייטים באורך קבוע המתעלמת מ־$/; השתמשו כשרוצים ספירת בייטים, לא רשומהeof- בדיקה האם ה־readlineהבא היה מחזירundef; מתנהג באופן מיוחד עבור*ARGV$/- מפריד רשומת קלט; שולט במצבי שורה, פסקה, slurp, ורשומה־קבועה$.- מספר השורה הנוכחי של הקלט, מוגדל על־ידי כלreadlineמוצלח