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

pos#

מדווח או קובע היכן התאמת ה־regex /g הבאה תתחדש במחרוזת.

pos קורא (או, כ־lvalue, כותב) את ה־offset שמנוע ה־regex שומר על סקלר לאחר התאמה גלובלית (m//g, s///g). ה־offset סופר תווים, לא בתים, והוא המיקום אחרי ההתאמה המוצלחת האחרונה - המקום שבו האיטרציה הבאה של /g תתחיל לסרוק. ללא ארגומנט pos פועל על $_.

תקציר#

pos SCALAR
pos $str = N
pos

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

offset שלם, או undef כאשר אין מיקום רשום. 0 הוא offset תקף ומשמעו ״תחילת המחרוזת״; הוא אינו זהה ל־undef, שמשמעו ״התאמת /g לא רצה, או האחרונה נכשלה ואיפסה את המיקום״. תמיד הבחינו בין השניים עם defined:

if (defined pos $str) {
    # a /g scan is in progress
}

כאשר משמש כ־lvalue, pos SCALAR מחזיר מיקום הניתן להשמה:

pos($str) = 5;          # next /g match starts at char offset 5

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

pos קורא וכותב את מיקום ה־regex לכל־סקלר המצורף לאופרנד שלו. ללא ארגומנט הוא מכוון ל־$_. ה־offset השמור הוא מה ש־\G מתעגן אליו בהתאמה הבאה, ולכן כל קריאה ל־pos עשויה לשנות היכן \G נקשר.

דוגמאות#

מהלכים על כל מילה במחרוזת עם /g בהקשר סקלר, באמצעות pos כדי לדווח על התקדמות:

my $s = "one two three";
while ($s =~ /(\w+)/g) {
    printf "%-5s ends at %d\n", $1, pos $s;
}
# one   ends at 3
# two   ends at 7
# three ends at 13

דילוג קדימה לפני התחלת הסריקה. ההתאמה הראשונה מתחילה ב־offset 4, לא 0:

my $s = "AAA BBB CCC";
pos($s) = 4;
$s =~ /(\w+)/g;
print $1, "\n";             # BBB

עיגון התאמת המשך לקודמת באמצעות \G. בלי \G המנוע היה סורק קדימה מעבר לכל פער; איתו, ההתאמה חייבת להתחיל בדיוק היכן שהאחרונה הסתיימה:

my $s = "12ab34cd";
while ($s =~ /\G(\d+)(\w+?)(?=\d|\z)/g) {
    print "num=$1 tail=$2\n";
}
# num=12 tail=ab
# num=34 tail=cd

הפעלה מחדש של סריקה על־ידי ניקוי המיקום:

pos($s) = undef;            # next /g starts from offset 0 again

מקרי קצה#

  • pos חשוף מכוון ל־$_. pos בתוך while (<>) { ... } מדווח אפוא על המיקום בשורת הקלט הנוכחית.

  • תווים, לא בתים. עבור מחרוזת המכילה תווים רבי־בתים, pos מחזיר את ה־offset בתווים. הפרגמה (המיושנת) use bytes עוברת ל־offsetים בבתים; קוד חדש לא צריך להסתמך עליה.

  • התאמת /g כושלת מאפסת את המיקום ל־undef - ה־/g הבא מתחיל מחדש ב־offset 0. הוסיפו את המתאם /c (m//gc) כדי לשמר את המיקום בכישלון, וזה האידיום הרגיל בעת הרכבת מספר תבניות חלופיות מעוגנות־\G מול אותה מחרוזת.

  • קריאות במהלך התאמה הן מיושנות. pos משקף את הסוף של ההתאמה הקודמת. ביטויים כמו (?{ pos() = 5 }) או s//pos() = 5/e משפיעים על ההתאמה הבאה, לא על זו הרצה כעת.

  • דגל התאמת אורך־אפס. קביעת pos גם מנקה את הדגל הפנימי הותאם עם אורך־אפס, כך שהתאמה ברוחב אפס נוספת באותו מיקום מותרת שוב. ראו את פרק הביצועים של מדריך ה־regex תחת סיום התאמת אורך־אפס.

  • אופרנד שאינו lvalue. pos דורש משתנה סקלר אמיתי עבור צורת ה־lvalue; pos("literal") = 3 היא שגיאת זמן הידור.

  • Offset 0 מול undef. pos של 0 משמעו ה־/g הבא מתחיל בהתחלה; undef משמעו אין מיקום שנקבע. הם מתנהגים באופן זהה בהתאמה הראשונה אך נבדלים לאחר שמצב דגל התאמת־האורך־אפס נלקח בחשבון.

הבדלים מ־upstream#

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

ראו גם#

  • m - המתאם /g הוא מה שיוצר ומקדם את המיקום ש־pos קורא; המתאם /c בכישלון משמר אותו

  • qr - הידור מקדים של תבנית פעם אחת, ולאחר מכן שימוש חוזר בה בלולאות /g מעוגנות־\G ללא פענוח חוזר

  • split - הדרך היומיומית האחרת להליכה במחרוזת בחלקים; אין pos מעורב, אך לעיתים קרובות בחירה נקייה יותר כשהמתחמים פשוטים

  • \G anchor

    • zero-width anchor that binds to the current pos; the main reason to touch pos in the first place

  • $_ - יעד ברירת המחדל של pos חשוף