# קבוצות ולכידות קיבוץ עושה שני דברים, שקל לבלבל ביניהם: הוא הופך רצף של רכיבי תבנית ליחידה אחת לצורכי כימות וחלופה, והוא שומר את מה שהיחידה התאימה לשימוש מאוחר יותר. ```perl /house(cat|keeper)/; # 'house' followed by 'cat' or 'keeper' /(ab){3}/; # 'ababab' /(\d{3})-(\d{4})/; # capture two groups separated by '-' ``` מעבר לצורת הלכידה הפשוטה `(…)`, Perl מספקת גן חיות קטן של מבנים בסוגריים: קבוצות שאינן לוכדות לקיבוץ נקי, לכידות בעלות שם לתבניות שמתעדות את עצמן, קבוצות אטומיות לבקרת חזרה לאחור, תת־תבניות רקורסיביות עבור מבנים מקוננים, תבניות מותנות להסתעפות לפי לכידות קודמות, ומבנה איפוס הענף לחלופות מקבילות. פרק זה מכסה את כולם. ## קבוצות לכידה: `$1`, `$2`, … כל זוג סוגריים בלא־escape בתבנית פותח קבוצת לכידה. לאחר התאמה מוצלחת, הטקסט שהותאם של הקבוצה ה־n נמצא ב־`$n`: ```perl if ($time =~ /(\d\d):(\d\d):(\d\d)/) { my ($hours, $minutes, $seconds) = ($1, $2, $3); } ``` בהקשר רשימה, התאמה מחזירה את רשימת המחרוזות הלכודות ישירות: ```perl my ($h, $m, $s) = $time =~ /(\d\d):(\d\d):(\d\d)/; ``` אם התבנית נכשלת, הרשימה ריקה — אידיום שימושי עבור ״לנתח או לוותר״: ```perl my ($h, $m, $s) = $time =~ /(\d\d):(\d\d):(\d\d)/ or die "not a time: $time"; ``` אין חסם עליון על מספר קבוצות הלכידה. הקבוצות ממוספרות כך שהסוגר השמאלי ביותר הוא קבוצה 1, הבא הוא קבוצה 2, וכן הלאה: ```default /(ab(cd|ef)((gi)|j))/ 1 2 34 ``` `$1` לוכד את הקבוצה החיצונית, `$2` את הפנימית הראשונה, `$3` את הבאה, `$4` את הפנימית ביותר. ### לכידת מחרוזת ריקה לעומת אי־התאמה כלל קבוצת לכידה שלא השתתפה בהתאמה — `$n` שלה הוא *לא־מוגדר*. קבוצה שהשתתפה והתאימה למחרוזת ריקה — `$n` שלה מוגדר ושווה ל־`""`. ההבחנה חשובה: ```perl "aba" =~ / a (x)* b \g1 a /x; # does NOT match "aba" =~ / a (x)? b \g1 a /x; # does NOT match "aba" =~ / a (x*) b \g1 a /x; # matches; $1 = "" "aba" =~ / a (x?) b \g1 a /x; # matches; $1 = "" ``` בשני המקרים הראשונים, המכמת *מחוץ* לקבוצה, ולכן הקבוצה עצמה לעולם לא נסגרה (המנוע התאים אפס איטרציות — לא נכנסו לקבוצה כלל). ההפניה לאחור `\g1` אין לה אפוא ערך להשוות אליו והיא נכשלת. בשני המקרים האחרונים, המכמת *בתוך* הקבוצה, ולכן הקבוצה רצה בדיוק פעם אחת ולכדה מחרוזת ריקה; `\g1` מתאים לאותה מחרוזת ריקה במיקום זה. הלקח: כאשר קבוצה היא אופציונלית, יש להציב את המכמת בתוכה אם רוצים את הסמנטיקה של ״התאמה ריקה נחשבת התאמה״. יש לבדוק לכידות תמיד עם `defined`, ולא לאמיתות — לכידה ריקה היא אמת־אך־ריקה תחת סמנטיקת מחרוזות: ```perl if ("x" =~ /(a)?(x)/) { print "1 is $1\n" if defined $1; # $1 is undef here print "2 is $2\n" if defined $2; } ``` ### התאמות שנכשלו אינן מאפסות את משתני הלכידה אם התאמה נכשלת, `$1`, `$2`, … שומרים על ערכיהם הקודמים מן ההתאמה ה *מוצלחת* האחרונה באותו תחום. זוהי תכונה: היא מאפשרת לכתוב סדרה של תבניות ספציפיות יותר ולהתייחס לאחר מכן ללכידות של ההתאמה הטובה ביותר. ```perl "foo" =~ /(\w+)/ and "" =~ /(\d+)/; # second fails print $1; # "foo" — first match's capture survives ``` זה גם מקור נפוץ לבלבול. יש לבדוק תמיד את ערך ההחזרה של ההתאמה לפני קריאת משתני הלכידה. ## קבוצות שאינן לוכדות: `(?:…)` אם נדרש הקיבוץ רק לכימות או לחלופה, ואין רצון בלכידה, יש להשתמש ב־`(?:…)`: ```perl /(?:ab){3}/; # 'ababab', no capture /(?:\d+\.)*\d+/; # a dotted decimal, no captures at all ``` קבוצות שאינן לוכדות הן רווח קטן במהירות ורווח גדול יותר בבהירות. הן מאותתות ״הקיבוץ הזה הוא לתחביר, לא לנתונים״. הן גם מונעות מספור מחדש של קבוצות הלכידה שכן חשובות: ```perl # match a number — $1 = whole, $2 = optional exponent value /([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE]([+-]?\d+))?)/; ``` ללא העטיפות `(?:…)`, `$2`, `$3`, `$4` כולם היו נקבעים, וה־`$2` המיועד (החזקה) היה זז ל־`$5`. הצורה המתוחמת `(?flags:…)` (למשל `(?i:cat)`, `(?xms:…)`) מצרפת מתאמים לתבנית הפנימית בלבד, וגם היא אינה לוכדת — ראו פרק [modifiers](modifiers.md). גם `split` נהנה מ־`(?:…)`. `split /(?:\s+)/` מפריד לפי רצפי רווח לבן מבלי להכניס את המפרידים לפלט; `split /(\s+)/` משאיר אותם במיקומים מתחלפים. ## לכידות בעלות שם `(?…)` או `(?'name'…)` נותן שם לקבוצה. ההתאמה שלה נגישה דרך ההאש `%+`: ```perl if ("2026-04-23" =~ /(?\d{4})-(?\d{2})-(?\d{2})/) { print "year = $+{year}\n"; # 2026 print "month = $+{month}\n"; # 04 print "day = $+{day}\n"; # 23 } ``` קבוצות בעלות שם מאכלסות גם את `$1`, `$2`, … בסדר השמאל־ימין הרגיל, כך שקוד המשתמש בשתי המוסכמות פועל. בתוך התבנית, יש להפנות לקבוצה בעלת שם באמצעות `\k` (או כל אחת מצורות הסוגריים/הציטוט להלן): ```perl /(?["'])(.*?)\k/; # same quote at start and end ``` השמות פועלים לפי כללי המזהים של Perl (`[_A-Za-z][_A-Za-z0-9]*`); הם אינם יכולים להתחיל בספרה ואינם יכולים להכיל מקפים. אם שתי קבוצות נפרדות חולקות שם, `$+{name}` מתייחס לקבוצה ה *שמאלית־ביותר־המוגדרת* בהתאמה. זה רצוי לעיתים רחוקות *מחוץ* לאיפוס ענף (`(?|…)`), שבו שמות משותפים הם אידיומטיים. ### `(?P…)` — תאימות ל־Python/PCRE עבור מתכנתים המסבים מן המודול `re` של Python או מ־PCRE, Perl מקבלת את הכתיבים בסגנון Python: | צורת Python | שקול ב־Perl | |-----------------|----------------| | `(?P...)` | `(?...)` | | `(?P=NAME)` | `\k` | | `(?P>NAME)` | `(?&NAME)` | צורות ה־Python פועלות אך אינן אידיומטיות ב־Perl; יש להעדיף את הצורות המקוריות בקוד חדש. ## הפניות לאחור הפניה לאחור בתבנית דורשת שמיקום מאוחר יותר יתאים *לאותו טקסט* שלכדה קבוצה קודמת — לא אותה תבנית, אלא אותם תווים בפועל. | צורה | מפנה אל | |--------------|---------------------------------------------------------| | `\1` … `\9` | קבוצת הלכידה הראשונה עד התשיעית (צורה ישנה) | | `\g1`, `\g2` | לכידה ממוספרת; שקול ל־`\1`, `\2` | | `\g{1}` | צורת סוגריים מסולסלים; נדרשת כאשר ספרות היו עוקבות אחרת | | `\g-1` | קבוצת הלכידה האחרונה שנפתחה (יחסי) | | `\g{-2}` | הקבוצה השנייה־האחרונה שנפתחה | | `\k` | לכידה בעלת שם | | `\k'name'` | זהה, צורת גרש בודד | | `\k{name}` | זהה, צורת סוגריים מסולסלים (מתירה רווחים סובבים) | | `\g{name}` | בעלת שם, כתיב חלופי | דוגמאות: ```perl # Match a three-letter word followed by a space and the same word. "the the other day" =~ /\b(\w{3})\s\1\b/; # $1 eq 'the' # Match a four-letter, three-letter, two-letter, or one-letter # run followed by itself. /^(\w{1,4})\1$/; # 'beriberi', 'booboo', 'coco', 'mama', 'papa' ``` ### `\g{…}` מול `\1` להסרת רב־משמעות יש להשתמש ב־`\g{…}` (או ב־`\k<…>`) כאשר ספרות או תווים בעלי מראה אוקטלי באים אחרי ההפניה, כדי למנוע רב־משמעות: ```perl /(\d)abc\g{1}23/; # the '1' refers to group 1, '23' is literal /(\d)abc\123/; # '\123' is octal 0x53 ('S'), not group 1 ``` הכלל של Perl לצורה ה־`\N` החשופה: `\1` עד `\9` תמיד מציינים הפניות לאחור. `\10`, `\11`, … מציינים הפניה לאחור *רק אם* מספר כזה של קבוצות לכידה נפתחו קודם לכן בתבנית; אחרת הם תווים מילוליים אוקטליים. בגלל זה `\g{...}` היא הצורה הבטוחה יותר כשהתבנית נבנית בשרשור. בשימוש בצורת הסוגריים המסולסלים, רווחים סובבים אופציונליים מותרים — `\g{ -1 }` ו־`\k{ name }` תקפים. ### הפניות לאחור יחסיות `\g-1`, `\g{-1}` מתייחסים לקבוצת הלכידה ה *קודמת מיד*; `\g{-2}` מתייחס לזו שלפניה; וכן הלאה. המרחק נספר לפי סוגריים *שנפתחו*, כולל בלתי־סגורים. זה חשוב כשמקטע תבנית משובץ בתוך אחר: ```perl my $pair = '([a-z])(\d)\g{-1}\g{-2}'; # a11a, g22g, x33x, ... # Embed it: outer group shifts numbering by 1, but relative # backreferences still work: "code=e99e" =~ /^(\w+)=$pair$/; # matches ``` ללא הפניות לאחור יחסיות, הדבר היה דורש לדעת כמה קבוצות מקדימות את `$pair` בכל מקום שיבוץ. הפניות בעלות שם והפניות יחסיות הופכות תבניות ארוכות לעמידות מול העתק־הדבק. ## קבוצות אטומיות: `(?>…)` `(?>…)` היא קבוצה שאינה לוכדת שתוכנה, ברגע שהותאם, *מחויב*. המנוע אינו יכול לחזור לאחור לתוך הקבוצה בכישלון — רק מעבר לה כשלמות. ```perl "aaab" =~ /a*ab/; # matches: a* gives back one 'a' "aaab" =~ /(?>a*)ab/; # does not match: a* takes all, refuses to give ``` הטיפול המלא נמצא בפרק [performance](performance.md). המבנה מתועד כאן מכיוון שתחבירו הוא קבוצה בסוגריים; מבנית הוא שייך לפרק הלכידות לצד `(?:…)`. מכמתים קנייניים (`*+`, `++`, `?+`, `{n,m}+`) הם סוכר תחבירי מדויק עבור `(?>…)` סביב האטום המכומת. הבאים שקולים: | קנייני | צורת קבוצה אטומית | |-------------|---------------------| | `PAT*+` | `(?>PAT*)` | | `PAT++` | `(?>PAT+)` | | `PAT?+` | `(?>PAT?)` | | `PAT{n,m}+` | `(?>PAT{n,m})` | גם הכתיב בצורה הארוכה `(*atomic:…)` מתקבל. ## תת־תבניות רקורסיביות ביטויי regex של Perl יכולים להפנות חזרה לקבוצת לכידה כאילו הייתה קריאה לתת־שגרה. המבנה מריץ מחדש את התבנית הלכודה במיקום הנוכחי. זה הופך מבנים רקורסיביים אמיתיים לניתנים להתאמה — סוגריים מאוזנים, S־ביטויים, סוגריים מקוננים — מבלי לחרוג מ־DSL ה־regex. | צורה | מבצע רקורסיה ל־ | |-------------|---------------------------------| | `(?R)` | התבנית כולה | | `(?0)` | זהה ל־`(?R)` | | `(?1)` | קבוצה 1 | | `(?2)` | קבוצה 2 (וכן הלאה) | | `(?-1)` | הקבוצה האחרונה שנפתחה (יחסי) | | `(?+1)` | הקבוצה הבאה שתיפתח (יחסי קדימה) | | `(?&NAME)` | קבוצה בעלת שם | | `(?P>NAME)` | זהה ל־`(?&NAME)` (תואם Python) | הערה: רקורסיה יחסית סופרת קבוצות לא־סגורות, שלא כמו הפניות לאחור יחסיות. `(?-1)` תמיד מציין את הקבוצה האחרונה שנפתחה, בין אם נסגרה ובין אם לא. מתאם של סוגריים מאוזנים: ```perl my $bal = qr/ (?(DEFINE) (? \( # opening paren (?: [^()]++ # non-paren run, possessive | (?&paren) # or a balanced sub-group, recursively )*+ \) # closing paren ) ) (?&paren) /x; "((a)(b(c)))" =~ /^$bal$/; # matches ``` הבלוק `(?(DEFINE)...)` מצהיר על תת־תבנית בעלת שם מבלי להתאים לכלום בעצמו; ה־`(?&paren)` שאחריו מפעיל את תת־התבנית, וה־`(?&paren)` הרקורסיבי בתוך הגוף הוא מה שנותן את העומק הבלתי־מוגבל. `(?R)` לא היה עובד כאן — הוא מבצע רקורסיה ל *כל* התבנית העוטפת, כולל העוגנים `^` ו־`$` שמתווספים באתר הקריאה, מה שכופה על כל רמת רקורסיה לדרוש תחילת־ וסוף־מחרוזת. תבנית רקורסיבית בעלת ניואנסים נוספים: התאמת פונקציה `foo(...)` שבה הארגומנט עצמו עשוי להכיל סוגריים מאוזנים. ```perl my $re = qr/( # group 1: full function call foo ( # group 2: parens with content \( ( # group 3: contents of parens (?: (?> [^()]+ ) # non-paren without backtracking | (?2) # recurse to group 2 )* ) \) ) )/x; 'foo(bar(baz)+baz(bop))' =~ /$re/ and print "1: $1\n2: $2\n3: $3\n"; # 1: foo(bar(baz)+baz(bop)) # 2: (bar(baz)+baz(bop)) # 3: bar(baz)+baz(bop) ``` ### מצב הלכידה בתוך רקורסיה כאשר קבוצה מבצעת רקורסיה לעצמה, לכידות שנקבעות בתוך הרקורסיה *אינן* נראות לקורא לאחר שהרקורסיה חוזרת. לקריאה הרקורסיבית יש מצב לכידה משלה, שמושלך עם החזרה. בגלל זה רוב התבניות הרקורסיביות עוטפות קבוצת לכידה משנית סביב הקריאה הרקורסיבית כשנדרש הטקסט המותאם: ```perl /(?(?&NAME_PAT))(?(?&ADDRESS_PAT)) (?(DEFINE) (?....) (?....) )/x ``` כאן `$+{NAME}` הוא הלכידה החיצונית; `$+{NAME_PAT}` אינו מוגדר מכיוון שהוא חי רק בתוך הרקורסיה. תקרת עומק הרקורסיה מהודרת לתוך המנוע. תבניות המבצעות רקורסיה ללא צריכת קלט נכשלות מיד במקום לרוץ לנצח — המנוע מזהה את המעגל. ### בלוקי `(DEFINE)` הבלוק `(?(DEFINE)…)` מחזיק תת־תבניות בעלות שם שאינן רצות בפני עצמן — הן מופעלות רק דרך `(?&NAME)`. כך כותבים regex שנראה כמו דקדוק קטן: ```perl my $email = qr/ \A (?&LOCAL) @ (?&DOMAIN) \z (?(DEFINE) (? [\w.+-]+ ) (? (?&LABEL) (?: \. (?&LABEL) )+ ) (?