מתאמים#

מתאמים משנים את אופן ההתאמה של תבנית מבלי לשנות את התבנית עצמה. הם מופיעים אחרי התוחם הסוגר של התאמה, החלפה או qr//:

"Hello" =~ /hello/i;        # case-insensitive match
$x =~ s/foo/bar/g;          # global substitution
my $re = qr/\d+/i;          # compiled pattern with /i

ניתן להטמיע את אותם מתאמים בתוך תבנית באמצעות (?flags) או (?flags:…), במגמה להגביל את השפעתם לחלק מהתבנית.

מערכת המתאמים המלאה#

מתאם

השפעה

/i

התאמה בלי רגישות לאותיות גדולות/קטנות

/m

רב־שורתי: ^ ו־$ מתאימים בכל \n

/s

חד־שורתי: . מתאים גם ל־\n

/x

מורחב: התעלם מרווחים לבנים ומהערות #

/xx

מורחב־מורחב: התעלם מרווחים לבנים גם בתוך […]

/g

גלובלי: התאם כמה שיותר פעמים

/c

אל תאפס את pos בכישלון (עם /g)

/r

s///r מחזיר את התוצאה במקום לשנות

/e

s///e מעריך את ההחלפה כקוד Perl

/ee

s///ee מעריך, ואז מעריך גם את התוצאה

/n

לא־לוכד: (…) מתנהג כמו (?:…)

/p

ללא פעולה; מתקבל לצורכי תאימות

/o

הדר את התבנית פעם אחת (נדרש לעיתים רחוקות; עדיף qr//)

/a

\d, \w, \s מוגבלים ל־ASCII

/aa

/a, ובנוסף /i אינו חוצה את הגבול ASCII/לא־ASCII

/u

סמנטיקת יוניקוד ללא קשר ל־use utf8

/l

השתמש ב־locale הנוכחי

/d

סמנטיקת מצב כפול — יש להימנע בקוד חדש

שמונת הראשונים הם המתאמים היומיומיים; מתאמי ערכת התווים /a, /u, /l, /d מכוסים בפירוט בפרק unicode ומסוכמים שוב כאן.

/i — בלי רגישות לאותיות גדולות/קטנות#

"Hello" =~ /hello/i;          # matches
"HELLO" =~ /[A-Z]/i;          # matches — class is insensitive too
"Grüße" =~ /GRÜSSE/i;         # matches under Unicode semantics

קיפול אותיות (case folding) ביוניקוד כולל מיפויים כמו ß ss, קיפול האסצט הגרמני, וכן הלאה. הטבלה המלאה נמצאת בתקן יוניקוד; עבור ASCII, /i עושה את המצופה.

ל־/i עלות ביצועים זניחה עבור ASCII. המימוש מקפל אותיות בזמן הידור — התבנית נושאת את ערכת התווים המקופלת, הקלט נקרא פעם אחת. קיפול אותיות ביוניקוד מסובך יותר (רצפים כמו ß ss), אך העבודה הנוספת תחומה ולעיתים רחוקות מופיעה בפועל.

/m — רב־שורתי#

משנה היכן ^ ו־$ מתאימים. ללא /m, הם מתאימים רק בקצוות החיצוניים של המחרוזת. עם /m, הם מתאימים גם בכל מעבר שורה משובץ.

my $x = "first\nsecond\nthird";

$x =~ /^second/;    # does not match
$x =~ /^second/m;   # matches — second is at start of a line
$x =~ /first$/m;    # matches
$x =~ /third$/m;    # matches

\A, \z, \Z נותרים עוגני מחרוזת מוחלטים גם תחת /m — ראו את פרק anchors and assertions.

/s — חד־שורתי#

גורם ל־. להתאים גם לתווי מעבר שורה.

my $x = "a\nb";
$x =~ /a.b/;        # does not match — . does not cross \n
$x =~ /a.b/s;       # matches

/m ו־/s עצמאיים. ניתן להשתמש בשניהם באותה התאמה. למרות השמות, הם אינם מתנגשים:

$x =~ /^a.b$/sm;    # . matches newline AND ^,$ are line-aware

/x — תבנית מורחבת#

מתעלם מרווחים לבנים מילוליים ומאפשר ל־# לפתוח הערות עד סוף השורה. חיוני עבור כל תבנית שאורכה יותר משורה.

לפני /x:

/^[+-]?\d+(\.\d*)?([eE][+-]?\d+)?$/;

אחרי:

/^
    [+-]?           # optional sign
    \d+             # integer part
    (\.\d*)?        # optional fraction
    ([eE][+-]?\d+)? # optional exponent
 $/x;

רווחים לבנים בתבנית מתעלמים מהם; רווחים לבנים שרוצים להתאים הופכים ל־\s, \ , או [ ]:

/\w+ \s+ \w+/x;      # three tokens: word, space, word (literal spaces ignored)
/\w+\s+\w+/x;        # equivalent
/key:[ ]value/x;     # literal space via bracket class
/key:\ value/x;      # literal space via backslash

# מתחיל הערה שמסתיימת במעבר השורה הבא. כדי להתאים # מילולי תחת /x, יש למלט אותו או להכניס אותו למחלקה.

הקבוצה ״Pattern White Space״ תחת /x עוקבת אחר Unicode UAX#31: SPACE, CHARACTER TABULATION, LINE FEED, LINE TABULATION, FORM FEED, CARRIAGE RETURN, NEXT LINE, PARAGRAPH SEPARATOR, LINE SEPARATOR. בפועל פוגשים רק ברווח, טאב ומעבר שורה של ASCII.

/xx — מורחב גם במחלקות#

בתוך […] רווחים לבנים אינם מתעלמים מהם תחת /x רגיל — [ab c] מתאים את a, b, ' ', או c. כדי להתעלם מרווחים לבנים גם בתוך מחלקות, יש להשתמש ב־/xx:

/[ab c]/xx;          # matches 'a', 'b', or 'c' — space ignored
/[ab\ c]/xx;         # the \ is needed to match a literal space
/[ ! @ ]/xx;         # matches '!' or '@' — visible spacing

/xx הוא קבוצת־על של /x. הוא נוח עבור מחלקות תווים שמסודרות לשם קריאוּת, במיוחד עם מחלקות מקוצרות:

/[ \d \s \-_,. ]+/xx;   # digits, whitespace, common punctuation

/xx נוסף ב־Perl 5.26. תבניות שנכתבו לפני כן נקראות כשורה; קוד חדש יכול להשתמש בו בחופשיות.

/g — גלובלי#

בהקשר סקלרי, שומר מיקום במחרוזת (pos $x) ומתקדם בכל פעם שהתבנית מתאימה, ובכך מאפשר איטרציה:

my $x = "cat dog house";
while ($x =~ /(\w+)/g) {
    print "$1 at ", pos($x), "\n";
}
# cat at 3
# dog at 7
# house at 13

בהקשר רשימה, מחזיר את כל ההתאמות בבת אחת:

my @words = $x =~ /(\w+)/g;   # ('cat', 'dog', 'house')

אם התבנית אינה מכילה לכידות, הקשר רשימה מחזיר את כל הטקסט שהותאם עבור כל התאמה:

my @digits = "abc123def456" =~ /\d+/g;   # ('123', '456')

עם מספר לכידות, כל איטרציה מחזירה את ה־tuple בסדר:

my @pairs = "a=1,b=2,c=3" =~ /(\w)=(\d)/g;
# ('a', '1', 'b', '2', 'c', '3')

/c — שמירת מיקום בכישלון#

כברירת מחדל, התאמת /g שכשלה מאפסת את pos ל־undef. תחת /gc, pos נותר בערכו הקודם — חיוני עבור lexers שנכתבו ידנית:

my $s = "123abc";
while (1) {
    if ($s =~ /\G(\d+)/gc)    { print "num $1\n"; next; }
    if ($s =~ /\G([a-z]+)/gc) { print "word $1\n"; next; }
    last;   # nothing matched; exit
}

ראו את פרק anchors and assertions עבור \G.

/r — החלפה לא־הרסנית#

s/// בדרך כלל משנה את מחרוזת המטרה ומחזיר את הספירה. s///r משאיר את המטרה בעינה ומחזיר את התוצאה:

my $name = "  Alice  ";
my $trimmed = $name =~ s/^\s+|\s+$//gr;
# $name is still "  Alice  "
# $trimmed is "Alice"

מאפשר שרשראות של החלפות ללא משתני ביניים:

my $clean = $input
    =~ s/\s+/ /gr          # collapse runs of whitespace
    =~ s/^ | $//gr         # trim ends
    =~ s/[^\x00-\x7f]//gr; # drop non-ASCII

כל s///r מחזיר את המחרוזת המומרת, שאותה מקבל הבא.

/e — הערכת ההחלפה#

חצי ההחלפה של s///e הוא קוד Perl, ולא מחרוזת במרכאות כפולות. ערך ההחזרה של הקוד מחליף את ההתאמה:

my $x = "numbers: 1 2 3 4";
$x =~ s/(\d+)/$1 * 2/ge;
# $x is now "numbers: 2 4 6 8"

/ee מעריך פעמיים: הקוד מחזיר מחרוזת, שמוערכת אז שוב כ־Perl. שימושי לעיתים רחוקות וקל לשימוש לרעה — יש להשתמש בו רק כאשר בטוחים. בפרק substitution יש דוגמאות מפורטות.

/n — לא־לוכד#

גורם לכל (…) רגיל להתנהג כמו (?:…). שימושי כאשר לתבנית ארוכה יש סוגריים אך ורק לצורך קיבוץ ורוצים להשאיר את $1, $2, … לא־מוגדרים:

"hello" =~ /(hi|hello)/n;    # matches, but $1 is not set

לכידות בשם (?<name>…) עדיין לוכדות תחת /n. נוסף ב־Perl 5.22.

/p — ללא פעולה#

/p הוא ללא־פעולה שקטה. ${^PREMATCH}, ${^MATCH}, ${^POSTMATCH} תמיד זמינים. מתקבל לצורכי תאימות לאחור, אך אינו תורם דבר בקוד חדש.

/o — הידור פעם אחת#

/o משבית הידור מחדש של תבנית שמשבצת משתנים. תבניות מהודרות גם נשמרות במטמון אוטומטית, ו־qr// מספק שליטה מפורשת. /o הוא לעיתים רחוקות הכלי הנכון; qr// ברור יותר וניתן להרכבה.

מתאמי ערכת תווים — /a, /aa, /u, /l, /d#

אלה שולטים באופן שבו המחלקות המקוצרות (\d, \w, \s), קיפול אותיות, וקבוצת מחלקות POSIX מתנהגים תחת שיקולי יוניקוד ו־locale. סיכום קצר כאן; הטיפול המלא נמצא בפרק unicode.

מתאם

התנהגות

/u

סמנטיקת יוניקוד מלאה. ברירת מחדל תחת use v5.12+.

/a

מגביל את \d, \w, \s, [[:…:]] ל־ASCII.

/aa

/a בנוסף ל־/i אינו חוצה את הגבול ASCII/לא־ASCII.

/l

עוקב אחר ה־locale POSIX הנוכחי של use locale.

/d

סמנטיקת מצב כפול. יש להימנע בקוד חדש.

/a, /u, /l, /d סותרים זה את זה — לכל היותר אחד יכול להיות בתוקף בכל פעם. /aa הוא חידוד של /a. אלה מתאמים לקביעה־אחת: (?d:…) פנימי אינו יכול לבטל /u חיצוני.

הבחירה היומיומית בקוד מודרני: use v5.12 (או מאוחר יותר) בוחר /u אוטומטית, וזה מה שרוצים עבור טקסט יוניקוד נכון. יש להוסיף /a רק כאשר התבנית חייבת לדחות תווים שאינם ASCII — בדרך כלל כי הקלט ידוע כ־ASCII בלבד ורוצים לאכוף זאת.

מתאמים מוטמעים#

(?flags) מפעיל דגלים עבור שאר הקבוצה העוטפת (או התבנית):

/(?i)yes/;         # case-insensitive, same as /yes/i

(?flags:…) מתחם את הדגלים לקבוצה הפנימית בלבד והוא לא־לוכד:

/Answer: ((?i)yes)/;   # only the 'yes' is case-insensitive
/Answer: ((?i:yes))/;  # clearer: scope is the group's contents

(?-flags) מכבה דגלים. ניתן לשלב ביניהם:

/(?i-m:pattern)/;   # turn on /i, turn off /m, within this group

מתאמים מוטמעים הם הכלי הנכון כאשר חלקים שונים של תבנית ארוכה צריכים מתאמים שונים. הם גם שימושיים בתבניות שנבנות באמצעות שיבוץ, שם (?i) המוטמע נע יחד עם קטע התבנית.

צורת הגג: (?^…)#

(?^flags) הוא קיצור עבור ״אפס את כל הדגלים, ואז החל אלה״. ההרחבה היא d-imnsx ואחריו הדגלים המפורטים. כך (?^x:…) פירושו ״דגלי ברירת מחדל פרט לכך ש־/x מופעל, ללא קשר לדגלים שהיו בתחום בחוץ״.

צורת הגג היא מה ש־Perl משתמשת בה כאשר היא מייצרת מחרוזת מתבניות מהודרות; ייתכן שתראו אותה בהודעות שגיאה או בפלט qr//. בקוד שנכתב ידנית היא שימושית לעיתים כאשר משבצים קטע תבנית שאינו צריך לרשת מתאמים מסביבתו:

my $strict = qr/(?^:foo|bar)/;   # always default flags
# ... no matter how this is interpolated.

דגל שלילי אינו חוקי אחרי הגג (הוא יהיה מיותר — הגג כבר ניקה הכל).

דגלים סותרים זה את זה#

/a ו־/aa דורסים זה את זה (האחרון מנצח); אותו דבר עבור /x ו־/xx. הם אינם מצטברים. (?xx-x:…) מכבה את כל התנהגות x, לא ״מחסר x אחד משניים״.

משפחת ערכת התווים /a, /d, /l, /u סותרת זו את זו; ציון של אחד מבטל את הציון של האחרים. אין אפשרות לכבות אותם באמצעות - בראש, רק להחליף ביניהם. לכן (?-d:…) היא שגיאה קטלנית; (?dl:…) גם כן קטלנית (שני דגלי ערכת תווים יחד).

/p מיוחד: נוכחותו בכל מקום בתבנית בעלת השפעה גלובלית (וההשפעה הזו היא ללא־פעולה).

סדר המתאמים#

בהתאמה או החלפה, סדר המתאמים הנגררים אינו משמעותי. /mgis ו־/sgmi זהים. יש לבחור סגנון בית ולדבוק בו.

כיצד נקרא ביטוי רגולרי — ארבעת השלבים#

כדי שמתאמים וצורות מוטמעות יעבדו, יש להבין ש־Perl קוראת ביטוי רגולרי בשלבים. השלבים:

  1. שלב A: המפענח מזהה את התוחם, מוצא את סוף התבנית. הערות (?#…) מוסרות כאן.

  2. שלב B: התבנית מפוענחת כמחרוזת בסגנון מרכאות כפולות. משתנים משובצים, רצפי בריחה מבושלים, \Q…\E מתורגם למילוט בסגנון quotemeta.

  3. שלב C: תחת /x או /xx, רווחים לבנים שאינם ממולטים והערות # מוסרים.

  4. שלב D: מהדר הביטויים הרגולריים קורא את התבנית המבושלת והמוסרת והופך אותה לצורה הפנימית של המנוע.

הסדר חשוב מכיוון שהשלבים B ו־D פועלים על ייצוגים שונים:

  • \Q$dir\E מתבשל בשלב B, לפני שמהדר הביטויים הרגולריים רואה אותו. עד שלב D תוכן המשתנה כבר עבר metaquote; מהדר הביטויים הרגולריים רואה תבנית מילולית.

  • \U…\E מפורש על ידי שלב B כהוראת בישול־מחרוזת (הפיכת התוכן לאותיות גדולות), וזה כמעט בוודאות לא מה שרוצים בתוך ביטוי רגולרי. יש להשתמש ב־\Q ו־\E לצורכי ביטוי רגולרי; \U רק כאשר רוצים שהטקסט המילולי של התבנית יהפוך לאותיות גדולות.

  • (?#comment) מוסר לפני שהשלב B רואה את התבנית בכלל. # מילולי בתוך (?#…) תקין. ) מילולי אינו תקין — ההערה מסתיימת ב־) הראשון.

המתאם /x חל בשלב C, בין השיבוץ להידור. משמעות הדבר היא שרווחים לבנים שמוכנסים על ידי משתנה משובץ אינם מוסרים על ידי /x:

my $sub = " a b ";       # contains literal spaces
"axb" =~ / x $sub x /x;  # the spaces in $sub are NOT stripped

אם רוצים שהתוכן המשובץ יציית ל־/x, יש להסיר את הרווחים הלבנים שלו במקור.

use re 'strict'#

use re 'strict' מעלה מספר תנאי רישול בביטויים רגולריים שבדרך כלל נסבלים לדרגת שגיאות בזמן הידור. הוא בתחום לקסיקלי. במצב strict:

  • { במיקום שאינו של כמת הוא שגיאה, לא מילולי.

  • [a-] (מקף בסוף מחלקה) הוא שגיאה.

  • שלילה חסרת תועלת של דגל שמופעל תמיד היא שגיאה.

  • (?-d) (ניסיון לכבות את /d) היא שגיאה ולא אזהרה.

  • [ ללא התאמה במחרוזת היא שגיאה.

מצב strict מומלץ עבור קוד חדש עתיר ביטויים רגולריים, במיוחד תבניות שמיוצרות אוטומטית שבהן שגיאות הקלדה קטנות לא מזוהות בבנייה רגילה. אינו ברירת מחדל כי הוא היה שובר תבניות ישנות שעובדות.

use re 'strict';

/abc{,1/;           # error in strict; warning otherwise
/[a-]/;             # error in strict

ראו גם#

  • פרק unicode/a, /aa, /u, /l, /d בפירוט, ובנוסף מה הם עושים למחלקות תווים ולקיפול אותיות.

  • פרק substitution/e, /r, /g, ו־/c בתפקידם הספציפי בהחלפה.

  • פרק basics — מודל הפענוח בארבעה שלבים בהופעתו הראשונה.

  • פרק anchors and assertions — אינטראקציות של \A, \z, \Z עם /m.

  • פרק performance — דיון על /o ומדוע qr// החליף אותו.

  • m, s, qr — הפניות לאופרטורים.