ביטויים רגולריים והתאמת תבניות

split#

חותך מחרוזת לרשימת שדות באמצעות מפריד regex.

split סורק את EXPR להתאמות של PATTERN ומחזיר את החלקים שבין ההתאמות כרשימה. הטקסט המותאם עצמו הוא המפריד ואינו נכלל בתוצאה - אלא אם התבנית מכילה קבוצות לכידה, ובמקרה זה כל לכידה הופכת לאיבר נוסף בפלט. בהקשר סקלר מוחזר גודל הרשימה.

אם PATTERN מושמט, split מתנהג כברירת המחדל של awk: רצפים של רווחים לבנים הם המפריד וכל רווח לבן מוביל ב־EXPR מוסר. אם EXPR מושמט, $_ מפוצל.

תקציר#

split /PATTERN/, EXPR, LIMIT
split /PATTERN/, EXPR
split /PATTERN/
split

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

רשימת תת־מחרוזות (שדות) בהקשר רשימה; ספירת השדות בהקשר סקלר. טקסט המפריד אינו לעולם חלק משדה.

my @fields = split /,/, "a,b,c";       # ("a", "b", "c")
my $n      = split /,/, "a,b,c";       # 3

פיצול של EXPR שהוא המחרוזת הריקה תמיד מניב אפס שדות, ללא קשר ל־LIMIT:

my @x = split /,/, "", -1;             # ()

לפני Perl 5.11, split בהקשר void או סקלר דרס את @_. Perl מודרני אינו עושה זאת; אסור להסתמך על תופעת הלוואי הישנה הזו.

הארגומנט LIMIT#

LIMIT שולט בכמה שדות מיוצרים, וקריטית, אם שדות ריקים גוררים נשמרים.

  • LIMIT חיובי - חסם עליון על מספר השדות. EXPR מפוצל לכל היותר LIMIT - 1 פעמים; השדה האחרון מחזיק את שאר המחרוזת מילולית. LIMIT = 1 משמעו אין פיצול כלל - מקבלים את כל המחרוזת בחזרה כאיבר יחיד.

    my @x = split /,/, "a,b,c", 1;       # ("a,b,c")
    my @x = split /,/, "a,b,c", 2;       # ("a", "b,c")
    my @x = split /,/, "a,b,c", 3;       # ("a", "b", "c")
    my @x = split /,/, "a,b,c", 4;       # ("a", "b", "c")
    
  • LIMIT שלילי - מטופל כגדול שרירותית. כמה שדות שאפשר מיוצרים, כולל כל השדות הריקים הגוררים.

    my @x = split /,/, "a,b,c,,,", -1;   # ("a", "b", "c", "", "", "")
    
  • LIMIT מושמט או אפס - כמו שלילי, למעט שדות ריקים גוררים שמוסרים. שדות ריקים מובילים תמיד נשמרים.

    my @x = split /,/, "a,b,c,,,";       # ("a", "b", "c")
    my @x = split /,/, ",,a,b";          # ("", "", "a", "b")
    
  • LIMIT מובלע בהשמת רשימה. בעת השמה לרשימה קבועה, Perl מגדיר את LIMIT ליותר באחד ממספר היעדים, כך שאין צורך לסרוק את השדות הגוררים. הבא מקבל LIMIT = 3 אוטומטית:

    my ($login, $passwd) = split /:/;
    

    בקוד קריטי לזמן, יש להעביר LIMIT מפורש במקום לתת לכל המחרוזת להיסרק.

מקרה הרווח הלבן בסגנון awk: split " "#

A literal single space as the pattern - split " ", not split / /

  • triggers a special case: PATTERN is treated as /\s+/ and any leading whitespace in EXPR is stripped before splitting. This matches classic awk behaviour.

my @x = split " ", "  Quick brown fox\n";
# ("Quick", "brown", "fox")

my @x = split " ", "RED\tGREEN\tBLUE";
# ("RED", "GREEN", "BLUE")

כדי לפצל על רווח יחיד מילולי בלבד, יש להשתמש בצורת ה־regex / / - היא אינה מקרה מיוחד:

my @x = split / /, " abc";             # ("", "abc")

מאז Perl 5.18, הטריגר הוא כל ביטוי שערכו הוא המחרוזת בעלת התו היחיד " " (לא רק מילולית), ומאז Perl 5.28 הכלל עובד נכון תחת use feature 'unicode_strings'. תחת Perl 5.39.9+ המתאם ברירת המחדל /x אינו משפיע על split STRING, כך ש־split " " עדיין משמעו אמולציית awk אפילו בתוך use re "/x". אם רוצים לפצל על רווח מילולי אחד תחת use re "/x", יש לכתוב split /(?-x: )/ או split /\x{20}/.

אם PATTERN מושמט לחלוטין, ברירת המחדל היא " ", כך ש־split חשוף הוא הצורה בסגנון awk.

מקרה התבנית הריקה: פיצול לתווים#

אם PATTERN מתאים למחרוזת הריקה, הפיצול קורה בכל מיקום התאמה - כלומר בין תווים.

my @x = split //, "abc";               # ("a", "b", "c")

ככלל ספציפי ל־split, אופרטור ההתאמה החשוף // אינו הצורה ”חזרה על ההתאמה המוצלחת האחרונה“ כאן; הוא התבנית הריקה המילולית. התאמה ברוחב אפס ממש בתחילת EXPR לעולם אינה מייצרת שדה מוביל ריק, ולכן פיצול של רווח מוביל מטופל כך:

my @x = split //, " abc";              # (" ", "a", "b", "c")   - 4, not 5
my @x = split //, " abc", -1;          # (" ", "a", "b", "c", "") - trailing empty with -1

התאמה ברוחב חיובי בתחילה כן מייצרת שדה מוביל ריק:

my @x = split / /, " abc";             # ("", "abc")

קבוצות לכידה הופכות לאיברים נוספים#

אם PATTERN מכילה קבוצות לוכדות, כל לכידה מוכנסת לרשימת הפלט עבור כל התאמת מפריד, בסדר שבו הקבוצות מוצהרות. קבוצה שאינה משתתפת בהתאמה תורמת undef. תוספות אלה אינן נספרות לקראת LIMIT.

my @x = split /-|,/    , "1-10,20", 3;
# ("1", "10", "20")

my @x = split /(-|,)/  , "1-10,20", 3;
# ("1", "-", "10", ",", "20")

my @x = split /-|(,)/  , "1-10,20", 3;
# ("1", undef, "10", ",", "20")

my @x = split /(-)|,/  , "1-10,20", 3;
# ("1", "-", "10", undef, "20")

my @x = split /(-)|(,)/, "1-10,20", 3;
# ("1", "-", undef, "10", undef, ",", "20")

יש להשתמש בזה כשרוצים לשמר את המפרידים לצד השדות - טיפוסי ל־tokenizers שבהם המתחמים הם עצמם חלק מזרם הפלט.

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

  • $_ - EXPR בברירת מחדל הוא זה כשלא ניתן ארגומנט שני.

  • @_ - Perl מודרני אינו נוגע בו. רלוונטי רק אם תומכים ב־perls שלפני 5.11.

  • משתני ההתאמה של מנוע ה־regex ($1, $2, …, $&, $', $``) **אינם** מוגדרים כתופעת לוואי של split, אפילו כש־PATTERN` לוכדת - הלכידות נכנסות לרשימה המוחזרת.

דוגמאות#

שורה קלאסית בסגנון CSV, ללא פסיקים משובצים:

my @cells = split /,/, "alice,bob,carol";    # ("alice", "bob", "carol")

ניתוח שורת /etc/passwd לשדות ידועים; LIMIT מובלע עוצר בשבעת המפרידים הראשונים:

my ($user, $pw, $uid, $gid, $gecos, $home, $shell)
    = split /:/, $line;

Tokenizing רווחים לבנים בסגנון awk, רווח לבן מוביל מושלך:

my @words = split " ", "   one\ttwo  three\n";
# ("one", "two", "three")

תווים של מחרוזת - התבנית הריקה:

my @chars = split //, "hello";               # ("h", "e", "l", "l", "o")

שמירת כל שדה ריק גורר לקורא מחמיר־ספירת־עמודות:

my @cols = split /\t/, $line, -1;

שימור מפרידים באמצעות לכידה - ניתן לשחזור בנסיעה חזור:

my @parts = split /([,;])/, "a,b;c";         # ("a", ",", "b", ";", "c")
my $same  = join "", @parts;                 # "a,b;c"

הצורה בברירת מחדל קוראת $_ ומבצעת פיצול רווחים לבנים בסגנון awk:

for (@lines) {
    my @f = split;                           # split " ", $_
    ...
}

מקרי קצה#

  • קלט ריק - split /X/, "" מחזיר את הרשימה הריקה עבור כל LIMIT, כולל -1.

  • LIMIT = 1 - אין פיצול; כל המחרוזת היא השדה האחד והיחיד. שימושי כשרוצים סמנטיקת split באופן מותנה מבלי לאבד את הקלט.

  • תבנית /^/ - מטופלת כאילו /^/m כך שהיא מתאימה בכל תחילת שורה, שזו ההתנהגות השימושית היחידה. מפצלת מחרוזת לשורות תוך שמירת שורות חדשות.

  • התאמה ברוחב אפס במיקום 0 - לעולם אינה מייצרת שדה מוביל ריק (ראו split //, " abc" לעיל).

  • התאמה ברוחב חיובי במיקום 0 - מייצרת שדה מוביל ריק, תמיד.

  • התאמה בסוף מחרוזת - מייצרת שדה גורר ריק, אשר אז מוסר אלא אם LIMIT אינו אפס.

  • תבניות עם מתאמים - המתאמים הרגילים של qr// (/i, /m, /s, /x, /u, /a, /l, /n) חלים. התבנית אינה חייבת להיות מילולית; כל ביטוי המייצר regex או מחרוזת עובד, ועצמי qr// מתקבלים.

  • מחרוזת רווח־יחיד שאינה מילולית - מ־Perl 5.18 והלאה, כל ביטוי המוערך ל־" " מפעיל את המקרה המיוחד בסגנון awk, לא רק המילולי " ".

  • split " " מול split / / - הראשון הוא רווח לבן בסגנון awk (\s+ עם הסרת רווח לבן מוביל), השני הוא רווח מילולי יחיד. השניים אינם ניתנים להחלפה.

  • רווח לבן ב־Unicode - תחת use feature 'unicode_strings' (ברירת מחדל מאז 5.28 למקרה בסגנון awk), split " " מתייחס לרווח לבן ב־Unicode כמפריד גם כן. מחוץ לאותו תיחום ההתנהגות מושפעת על ידי ה־“Unicode Bug“.

הבדלים מהמקור#

תואם במלואו ל־Perl 5.42 במקור.

ראו גם#

  • join - פעולה הפוכה; תופרת רשימה חזרה למחרוזת עם דבק נבחר

  • m - אופרטור ההתאמה; כשרוצים למצוא משהו במקום לחתוך את המחרוזת סביבו

  • qr - הידור מראש של תבנית פעם אחת לקריאות split חוזרות בלולאה חמה

  • index - איתור תת־מחרוזת קבועה ללא בניית הרשימה המלאה של שדות; זול יותר כשצריך רק את הפיצול הראשון

  • substr - חילוץ לפי offset בייט/תו כשגבולות השדה הם מיקומיים, לא מתוחמים