glob#
מרחיב תבנית שם קובץ בסגנון shell לרשימת הנתיבים התואמים.
glob לוקח מחרוזת תבנית כגון "*.c" או "src/**/*.pm" ומחזיר את שמות הקבצים על הדיסק התואמים, באותו סגנון ש־Unix shell היה מפיק. בהקשר רשימה הוא מחזיר את כל ההתאמות בבת אחת; בהקשר סקלרי הוא מתנהג כאיטרטור עם מצב, מחזיר התאמה אחת לכל קריאה ו־undef כאשר הרשימה מוצתה. ללא ארגומנט, glob מרחיב את התבנית ב־$_.
תקציר#
glob EXPR
glob
<PATTERN>
מה מקבלים בחזרה#
בהקשר רשימה, רשימה (אולי ריקה) של שמות קבצים. רשימה ריקה משמעה שהתבנית לא התאימה - זו אינה שגיאה ואינה קובעת את $!.
בהקשר סקלרי, glob הוא איטרטור: כל קריאה מחזירה את ההתאמה הבאה, ולאחר ההתאמה האחרונה קריאה נוספת מחזירה undef. מצב האיטרטור הוא לכל־אתר־קריאה, כך ששתי לולאות while (my $f = glob ...) במיקומי מקור שונים אינן מפריעות זו לזו.
my @mp3 = glob "*.mp3"; # list context
while (my $f = glob "*.mp3") { } # scalar context, iterator
מצב גלובלי שהוא נוגע בו#
הקיצור <...> וכיצד Perl בוחר בו#
<*.c> הוא תחביר חלופי ל־glob("*.c"). צורת סוגריים־משולשים חולקת reader עם <FH> (readline); המפענח מחליט באיזו מהן התכוונתם בזמן ההידור על־סמך מה שיושב בין סוגריים־המשולשים:
Bareword שיכולה להיות מטפל קובץ (
<STDIN>,<FH>) →readline.סקלר פשוט (
<$fh>) →readlineעל אותו מטפל.כל דבר הנראה כתבנית (
<*.c>,<"*.txt">,<${dir}/*>) →glob.
הפונקצייה ה־named glob חד־משמעית וניתנת לחיפוש טוב יותר. העדיפו אותה בקוד חדש; פנו ל־<...> רק לתבניות הקצרות ביותר לזריקה חד־פעמית.
my @txt = <"*.txt">; # same as glob '"*.txt"'
my @txt = glob "*.txt"; # recommended
רווחים מפצלים את התבנית#
glob מפצל את הארגומנט שלו ברווחים ומתייחס לכל סגמנט כתבנית נפרדת. התוצאות משורשרות:
my @sources = glob "*.c *.h"; # all .c OR .h files
my @all = glob ".* *"; # every entry in cwd
כדי לבצע glob על שם קובץ שמכיל רווחים בעצמו, עטפו אותו בזוג מירכאות פנימי כדי שהפיצול יראה סגמנט אחד:
my @spacey = glob '"*e f*"'; # files with "e f" in the name
my @spacey = glob q("*e f*"); # same, q() for clarity
my @spacey = <"*e f*">; # same via the shortcut form
שילוב משתנה לתוך תבנית עם רווחים:
my @spacey = glob "'*${var}e f*'";
my @spacey = glob qq("*${var}e f*");
אם כלל פיצול־הרווחים מפריע, השתמשו ב־bsd_glob של File::Glob ישירות - הוא לוקח את התבנית מילולית.
הרחבת סוגריים מסולסלים ללא wildcard#
אם התווים המיוחדים היחידים הם סוגריים מסולסלים לא־ריקים, glob כלל אינו נוגע במערכת הקבצים: הוא רק מונה את המכפלה הקרטזית של החלופות. הדבר שימושי ליצירת צירופי מחרוזות:
my @pairs = glob "{apple,tomato,cherry}={green,yellow,red}";
# apple=green, apple=yellow, apple=red,
# tomato=green, tomato=yellow, tomato=red,
# cherry=green, cherry=yellow, cherry=red
File::Glob - המנוע, והאפשרויות שלו#
glob ממומש על־גבי bsd_glob של File::Glob. ייבוא תגי המודול מכוון את ההתנהגות עבור יחידת ההידור כולה:
:nocase- התאמה ללא רגישות לאותיות גדולות וקטנות.:case- אילוץ התאמה רגישה לאותיות גדולות וקטנות (ברירת המחדל ברוב מערכות הקבצים של Unix).:globally- מחליף את אופרטור ה־globהליבתי ב־bsd_globכך שכלglob(...)ו־<...>בקובץ קולטים את האפשרויות שלכם.
use File::Glob qw(:globally :nocase);
my @txt = glob "readme*"; # README, readme.txt, Readme.md
קראו ל־bsd_glob ישירות כשצריך דגלים לכל קריאה, או כשרוצים לעקוף את כלל פיצול־הרווחים:
use File::Glob qw(bsd_glob GLOB_TILDE GLOB_BRACE);
my @files = bsd_glob("~/docs/*.{md,rst}", GLOB_TILDE | GLOB_BRACE);
דוגמאות#
לפרט כל קובץ מקור של Perl בספרייה הנוכחית:
my @perl_files = glob "*.pl *.pm";
איטרציה על קבצי MP3 אחד בכל פעם - שימושי כשהרשימה עשויה להיות גדולה ולא רוצים להממש אותה:
while (my $song = glob "*.mp3") {
process($song); # one filename per iteration
}
תבניות רקורסיביות אינן מובנות; * אינו חוצה את /. סרקו את העץ עם File::Find או שלבו את glob עם מעבר מפורש:
my @all_c;
for my $dir (glob "src/*") {
push @all_c, glob "$dir/*.c" if -d $dir;
}
השתמשו בצורת האיטרטור בתנאי while - התוצאה משוייכת ל־$_ ונבדקת למוגדרות, כך ששמות קבצים כמו "0" אינם מסיימים את הלולאה:
while (<*.log>) {
unlink $_ if -M $_ > 30; # older than 30 days
}
התאמה ללא רגישות לאותיות גדולות וקטנות עבור קובץ שלם:
use File::Glob qw(:globally :nocase);
my @readmes = glob "readme*";
מקרי קצה#
אין התאמות: מחזיר רשימה ריקה. אין אזהרה, אין קביעה של
$!. אם צריך ״התבנית חייבת הייתה להתאים״, בדקו אתscalar @filesבעצמכם.globללא ארגומנט: משתמש ב־$_.globעירום בתוךwhile (<>)רק לעיתים נדירות הוא מה שרוצים - התבנית תהיה כל שורת קלט שזה עתה קראתם.while (glob ...)משייך ל־$_ובודק מוגדרות: שם קובץ"0"הוא שקר תחת כללי בוליאן רגילים, אבל הלולאה עדיין רצה כי התנאי הואdefined $_. הדבר תואם את הכלל עבורreadlineבאותו מיקום.Wildcards ורווחים: כלל הפיצול־ברווחים אומר ש־
glob "a b"מחפש אתaואתbכשתי תבניות, לא את המחרוזת המילולית"a b". השתמשו במירכאות פנימיות או ב־bsd_globכאשר שם הקובץ מכיל רווחים באופן לגיטימי.קבצים מוסתרים:
.מוביל אינו מותאם על־ידי*- יש צורך בסגמנט.*מפורש (glob ".* *") כדי לכלול dotfiles. הדבר תואם סמנטיקת shell glob, לא סמנטיקת regex.הרחבת tilde:
glob "~/foo"עובד כיFile::Globמרחיב~כברירת מחדל. כשכותבים אותו דרךbsd_globללאGLOB_TILDEבדגלים, מקבלים~מילולי.שילוב בתוך
<...>:<$var/*.c>משלב את$varבזמן ריצה. שימוש בצורת סוגריים־משולשים אינו פוטר אתכם מכללי המירכאות־הכפולות הרגילים של Perl.עמימות סוגריים־משולשים:
<FOO>היא קריאת מטפל,<$foo>היא קריאת מטפל,<*.c>הוא glob.<$foo/*.c>- סקלר אחד בתוספת תווי תבנית - הוא glob. ההכרעה היא בזמן ההידור; שינויים בזמן ריצה ל־$fooאינם מחליטים אותה מחדש.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
opendir- פותח מטפל ספרייה למעבר עדין יותר מזה שהתאמת תבניות נותנתreaddir- קורא רשומות ממטפל ספרייה אחת בכל פעם; שלבו עםopendirכשצריך כל רשומה (כולל אלו ש־globמסתיר, כמו dotfiles) או מידע על טיפוס קובץreadline- המשמעות האחרת של<...>; חולק את תחביר סוגריים־המשולשים אך קורא שורות ממטפל קובץFile::Glob- המימוש הבסיסי; השתמשו ב־bsd_globישירות עבור דגלים לכל־קריאה וכדי לעקוף את כלל פיצול־הרווחים$_- מקור תבנית ברירת המחדל עבורglobעירום, והמשתנה שמשוייך באופן מובלע כאשרglobמשמש כתנאי לולאתwhile/for