Sometimes we need to find only those matches for a pattern that are followed or preceded by another pattern.
هناك صيغة خاصة لذلك ، تسمى “lookahead” و “lookbehind” ، يشار إليها معًا باسم “lookaround”.
في البداية ، دعنا نجد السعر من السلسلة مثل الموضوع: 1 ديك رومي يكلف 30 يورو. أي: رقم متبوعًا بعلامة €.
Lookahead
الصيغة هي: X (؟ = Y) ، وتعني "ابحث عن X ، لكن تطابق فقط إذا تبعها "pattern: Y". قد يكون هناك أي نمط بدلاً منpattern:Xوpattern:Y`.
بالنسبة لرقم صحيح متبوعًا بـ€, سيكون regexp
\d+(?=€):
let str = '1 turkey costs 30€';
alert(str.match(/\d+(?=€)/)); // 30, the number 1 is ignored, as it's not followed by €
يرجى ملاحظة: lookahead هو مجرد اختبار ، ومحتويات "نمط قوسين: (؟ = …)غير مدرجة في النتيجةmatch:30`.
عندما نبحث عن "pattern: X (؟ = Y)` ، يعثر محرك التعبير العادي على “pattern: X” ثم يتحقق مما إذا كان هناك “pattern: Y” بعده مباشرة. إذا لم يكن الأمر كذلك ، يتم تخطي المطابقة المحتملة ، ويستمر البحث.
من الممكن إجراء اختبارات أكثر تعقيدًا ، على سبيل المثال النمط: X (؟ = Y) (؟ = Z) يعني:
- ابحث عن
النمط: X. - تحقق مما إذا كان “النمط: Y” مباشرةً بعد “النمط: X” (يمكنك التخطي إذا لم يكن كذلك).
- تحقق مما إذا كان “النمط: Z” هو أيضًا مباشرةً بعد “النمط: X” (يمكنك التخطي إذا لم يكن كذلك).
- في حالة اجتياز كلا الاختبارين ، فإن “النمط: X” هو تطابق ، وإلا فتابع البحث.
بمعنى آخر ، يعني هذا النمط أننا نبحث عن X متبوعًا بـ Y و Z في نفس الوقت.
هذا ممكن فقط إذا كان النموذجان “pattern: Y” و “pattern: Z” لا يستبعد أحدهما الآخر.
على سبيل المثال ، \ d + (؟ = \ s) (؟ =. * 30) يبحث عن \ d + فقط إذا كان متبوعًا بمسافة ، ويوجد 30 في مكان ما بعده:
For example, \d+(?=\s)(?=.*30) looks for \d+ that is followed by a space (?=\s), and there’s 30 somewhere after it (?=.*30):
let str = '1 turkey costs 30€';
alert(str.match(/\d+(?=\s)(?=.*30)/)); // 1
في سلسلتنا التي تتطابق تمامًا مع الرقم 1.
Negative lookahead
لنفترض أننا نريد كمية بدلاً من ذلك ، وليس سعرًا من نفس السلسلة. هذا رقم نمط: \ d + ، وليس متبوعًا بـ الموضوع: €.
لذلك ، يمكن تطبيق lookahead سلبي.
الصيغة هي: X (؟! Y) ، وتعني "search X ، ولكن فقط إذا لم يتبعها “pattern: Y`”.
let str = '2 turkeys cost 60€';
alert(str.match(/\d+\b(?!€)/g)); // 2 (the price is not matched)
Lookbehind
يسمح Lookahead بإضافة شرط لـ “ما يلي”.
Lookbehind مشابه ، لكنه يبدو في الخلف. أي أنه يسمح بمطابقة النمط فقط إذا كان هناك شيء قبله.
الصيغة هي:
- نظرة إيجابية خلف:
(؟ <= Y) X، تطابقX، ولكن فقط في حالة وجود "pattern: Y` قبلها. - مظهر سلبي خلف:
(؟ <! Y) X، يطابقX، ولكن فقط في حالة عدم وجودYقبله.
على سبيل المثال ، دعنا نغير السعر إلى الدولار الأمريكي. عادةً ما تكون علامة الدولار قبل الرقم ، لذلك للبحث عن $ 30 ، سنستخدمالنمط: (؟ <= \ $) \ d +- مبلغ يسبقهالموضوع: $`:
let str = '1 turkey costs $30';
// the dollar sign is escaped \$
alert(str.match(/(?<=\$)\d+/)); // 30 (skipped the sole number)
وإذا احتجنا إلى الكمية – رقمًا ، لا يسبقه "الموضوع: $، فيمكننا استخدام النمط السلبي خلف ": (؟ <! \ $) \ d +:
let str = '2 turkeys cost $60';
alert(str.match(/(?<!\$)\b\d+/g)); // 2 (the price is not matched)
التقاط المجموعات
بشكل عام ، لا تصبح المحتويات الموجودة داخل الأقواس حول جزء من النتيجة.
على سبيل المثال في النموذج \ d + (؟ = €) ، لا يتم التقاط علامة € كجزء من المباراة. هذا طبيعي: نحن نبحث عن رقم نقش: \ d + ، بينما نقش: (؟ = €) هو مجرد اختبار يجب أن يتبعه الموضوع: €.
ولكن في بعض المواقف ، قد نرغب في التقاط تعبير lookaround أيضًا ، أو جزء منه. أن من الممكن. ما عليك سوى لف هذا الجزء بأقواس إضافية.
في المثال أدناه ، تم تسجيل “نمط علامة العملة: (€ | kr)” ، بالإضافة إلى المبلغ:
let str = '1 turkey costs 30€';
let regexp = /\d+(?=(€|kr))/; // extra parentheses around €|kr
alert(str.match(regexp)); // 30, €
وإليك نفس الشيء بالنسبة إلى: lookbehind:
let str = '1 turkey costs $30';
let regexp = /(?<=(\$|£))\d+/;
alert(str.match(regexp)); // 30, $
ملخص
Lookahead و lookbehind (يشار إليهما عادةً باسم “lookaround”) مفيدان عندما نرغب في مطابقة شيء ما اعتمادًا على السياق قبله / بعده.
بالنسبة إلى regexps البسيطة ، يمكننا القيام بنفس الشيء يدويًا. هذا هو: مطابقة كل شيء ، في أي سياق ، ثم التصفية حسب السياق في الحلقة.
تذكر أن str.match (بدون العلامة g) و str.matchAll (دائمًا) ترجع التطابقات كمصفوفات مع خاصيةindex ، حتى نعرف مكانها بالضبط في النص ، ويمكننا التحقق من سياق الكلام.
لكن بشكل عام يكون البحث أكثر ملاءمة.
أنواع Lookaround:
| النمط | النوع | التطابق |
|---|---|---|
X(?=Y) |
Positive lookahead | X إذا تبعه Y |
X(?!Y) |
Negative lookahead | ``pattern: Xإذا لم يتبعه pattern: Y` |
(?<=Y)X |
Positive lookbehind | X إذا بعده Y |
(?<!Y)X |
Negative lookbehind | X إذا لم يكن بعده Y |
التعليقات
<code>، وللكثير من السطور استخدم<pre>، ولأكثر من 10 سطور استخدم (plnkr, JSBin, codepen…)