קלט/פלט

printf#

כותב מחרוזת מפורמטת למטפל קובץ.

printf הוא print FILEHANDLE sprintf(FORMAT, LIST) עם חריג אחד מכוון: מפריד רשומות הפלט $\ אינו מצורף. כללי היעד הם בכל מקרה כללי print - bareword או סקלר פשוט כמטפל קובץ ממש לפני רשימת הארגומנטים, או צורת הבלוק {EXPR} עבור כל דבר מורכב יותר. אם FILEHANDLE מושמט, הפלט הולך למטפל הנבחר כעת (ראו select), שמתחיל את חייו כ־STDOUT.

ראו sprintf לעיון במציין הפורמט - כל ה־%d, %s, %.3f, %*d, %1$s, %v, דגלי ווקטור, %f הרגיש ל־locale, וכן הלאה. עמוד זה מכסה רק את המשטח הייחודי ל־printf: פתרון מטפל הקובץ, כלל הפורמט־ראשון, וההתנהגויות המוזרות סביב הצורה ללא־ארגומנטים.

תקציר#

printf FORMAT, LIST
printf FILEHANDLE FORMAT, LIST
printf {EXPR} FORMAT, LIST
printf FH                      # bareword filehandle, $_ as format

מה מקבלים בחזרה#

1 בהצלחה, undef בכשל (כאשר $! נקבע). כמו ב־print, ערך ההחזרה נבדק לעיתים נדירות עבור כתיבות ל־STDOUT / STDERR, וכדאי לבדוק אותו עבור כתיבות לקבצים, pipes, וסוקטים שבהם כתיבות חלקיות ו־pipes שבורים חשובים.

printf $fh "%-20s %8d\n", $name, $count
    or die "write to $path failed: $!";

מצב גלובלי שהוא נוגע בו#

  • מטפל הקובץ הנבחר (משתנה דרך select): היעד כאשר FILEHANDLE מושמט. מתחיל כ־STDOUT.

  • $\ (מפריד רשומות הפלט): אינו מצורף בכוונה - זהו ההבדל הסמנטי היחיד בין printf FORMAT, LIST לבין print FILEHANDLE sprintf(FORMAT, LIST). שימו את השורה החדשה במחרוזת הפורמט.

  • $, (מפריד שדות הפלט): אינו נלקח בחשבון. printf משלב את אלמנטי הרשימה לתוך הפורמט בהתאם להמרות, לא באמצעות מפריד.

  • $_: משמש כפורמט כאשר גם FORMAT וגם LIST מושמטים, לא מצורף לפלט. כמעט אף פעם לא מה שאתם רוצים; ראו מקרי קצה.

  • $!: נקבע בכשל כתיבה.

  • $|: דגל autoflush עבור המטפל הנבחר. printf משתמש ב־buffering דרך PerlIO כמו print.

  • locale LC_NUMERIC: כאשר use locale פעיל ו־POSIX::setlocale נקרא, מפריד הנקודה העשרונית להמרות נקודה־צפה (%f, %e, %g) עוקב אחרי ה־locale.

דוגמאות#

כתיבה מפורמטת בסיסית ל־STDOUT. בניגוד ל־say או ל־print־עם־$\, השורה החדשה הסופית באחריותכם:

printf "%s is %d years old\n", $name, $age;

רוחב ודיוק עבור עמודה מסודרת:

printf "%-20s %8.2f\n", $item, $price;

כתיבה למטפל קובץ. bareword וסקלר פשוט עובדים ישירות; ללא פסיק בין מטפל הקובץ לפורמט:

open my $fh, ">", "report.txt" or die $!;
printf $fh "%5d  %s\n", $n, $msg;
close $fh;

מטפל קובץ המוחזק בביטוי מורכב יותר - השתמשו בצורת הבלוק {EXPR} (אותו כלל כמו ב־print):

my @logs = (\*STDOUT, \*STDERR);
printf { $logs[$severity] } "[%s] %s\n", $tag, $msg;

פורמט חוזר עם רשימה המשתרעת על־פני מספר רשומות. printf אינו מיישם מחדש את הפורמט לכל רשומה - המרות נצרכות פעם אחת, משמאל לימין:

printf "%s=%s\n", "user", "alice";       # "user=alice\n"
printf "%s=%s\n%s=%s\n",                 # two records, one call
       "user", "alice", "host", "db1";

מפריד נקודה עשרונית רגיש ל־locale:

use POSIX qw(setlocale LC_NUMERIC);
use locale;
setlocale(LC_NUMERIC, "de_DE.UTF-8");
printf "%.2f\n", 1234.5;                 # "1234,50\n"

מקרי קצה#

  • LIST לא נמסר, $_ הופך לפורמט. printf; ו־printf FH; (מטפל קובץ כ־bareword) מפרמטים את $_. אם $_ מכיל המרות % כלשהן הן מתפרשות כנגד רשימת ארגומנטים ריקה - כל %s / %d הופך למחרוזת הריקה ו־use warnings פולט אזהרת Missing argument in printf. כדי לכתוב את $_ ככתבו וכלשונו השתמשו ב־print, לא ב־printf.

  • מטפל קובץ עקיף ללא רשימה הוא עמום ואינו נתמך. printf $fh; מפרסר את $fh כפורמט, לא כמטפל הקובץ. אם אתם צריכים צורה ללא־ארגומנטים עם מטפל קובץ סקלרי, עברו דרך print או העבירו פורמט מפורש: printf $fh "%s", $_.

  • הארגומנט הראשון הוא תמיד הפורמט. printf(@_) משתמש ב־$_[0] כפורמט ובאלמנטים הנותרים כארגומנטים - זהו כלל פרסור, לא מוסכמה. בנו את הפורמט בכוונה; אל תשטחו רשימות שנמסרו על־ידי המשתמש לתוך printf אלא אם האלמנט הראשון ידוע כבטוח.

  • $\ אינו מצורף. הטמעת "\n" בפורמט היא המסיים האידיומטי. קביעת local $\ = "\n" אינה משפיעה על פלט printf.

  • $, מתעלמים ממנו. מפריד שדות הפלט הוא מושג של print; printf אינו מצרף דבר - הוא מחליף.

  • printf (…) מתפרסר כקריאת פונקציה, בדיוק כמו print. printf ("%d", 1)*2 מחשב את printf(...) ואז כופל את ערך ההחזרה ב־2 ומשליך אותו. עטפו את כל רשימת הארגומנטים בסוגריים או הקדימו ב־+ אם צריך לפענח את העמימות.

  • מטפל קובץ סגור: מחזיר undef וקובע את $! ל־"Bad file descriptor". תחת use warnings נפלטת אזהרת printf() on closed filehandle.

  • שכבות קידוד: printf כותב דרך מחסנית PerlIO של המטפל. שכבת :utf8 או :encoding(...) מקודדת בדרך החוצה; מטפל במצב־בתים עם מחרוזת תווים רחבים פולט Wide character in printf וכותב נקודות קוד גולמיות.

  • SIGPIPE על pipe/סוקט סגורים: פעולת ברירת המחדל מסיימת את התהליך. התקינו $SIG{PIPE} כדי להפוך זאת לכשל כתיבה שניתן לבדוק.

  • אל תשתמשו ב־printf כאשר print מספיק. printf "%s", $msg איטי יותר ונוטה לשגיאות יותר מ־print $msg - מחרוזת הפורמט נפרסרת בכל קריאה, ו־% נדודה ב־$msg המשמשת כפורמט הופכת לבאג שמחכה לקרות.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • print - כתיבה לא־מפורמטת עם אותם כללי מטפל קובץ; מהיר יותר, ומצרף את $\ במקום ש־printf אינו מצרף

  • sprintf - בונה את המחרוזת המפורמטת מבלי לכתוב אותה; עיון מציין הפורמט נמצא כאן

  • say - print עם $\ המאולץ ל־"\n"; בחרו בו כאשר כל רשומה מסתיימת בשורה חדשה

  • select - שנו לאיזה מטפל קובץ הצורה ללא־מטפל־קובץ של printf כותבת

  • $\ - מפריד רשומות הפלט; אינו מצורף בכוונה על־ידי printf

  • $_ - משמש כפורמט כאשר גם FORMAT וגם LIST מושמטים