٣٠ مايو ٢٠٢٠

علم ثابت "y" ، البحث في الموضع

تسمح العلامة y بالبحث في الموضع المحدد في السلسلة المصدر.

لفهم حالة استخدام علامة “pattern: y” ، ومعرفة مدى روعتها ، دعنا نستكشف حالة استخدام عملية.

إحدى المهام الشائعة لـ regexps هي “التحليل المعجمي”: نحصل على نص ، على سبيل المثال في لغة البرمجة ، وتحليلها للعناصر الهيكلية.

على سبيل المثال ، يحتوي HTML على علامات وسمات ، وشفرة JavaScript لها وظائف ، ومتغيرات ، وما إلى ذلك.

تعد كتابة المحللات المعجمية مجالًا خاصًا ، مع أدواته وخوارزمياته الخاصة ، لذلك لا نتعمق في ذلك ، ولكن هناك مهمة مشتركة: قراءة شيء ما في الموضع المحدد.

على سبيل المثال لدينا سلسلة التعليمات البرمجية let varName =" value " ، ونحتاج إلى قراءة اسم المتغير منه ، الذي يبدأ في الموضع 4.

سنبحث عن اسم متغير باستخدام نمط regexp : \ w +. في الواقع ، تحتاج أسماء متغيرات جافا سكريبت إلى regexp أكثر تعقيدًا قليلاً لمطابقة دقيقة ، ولكن هنا لا يهم.

استدعاء str.match (/ \ w + /) سيجد الكلمة الأولى فقط في السطر. أو جميع الكلمات التي تحمل علامة g. ولكننا نحتاج إلى كلمة واحدة فقط في الموضع 4.

للبحث من الموضع المحدد ، يمكننا استخدام الطريقة regexp.exec (str).

إذا كان “regexp” لا يحتوي على علامات g أو y ، فإن هذه الطريقة تبحث عن المطابقة الأولى في السلسلة str ، تمامًا مثلstr.match (regexp). لا تثير اهتمامنا مثل هذه الحالة البسيطة التي لا توجد أعلام فيها.

إذا كان هناك علامة g ، فسيتم البحث في السلسلةstr ، بدءًا من الموضع المخزن في خاصية regexp.lastIndex. وإذا وجد تطابقًا ، فعيّن “regexp.lastIndex” إلى الفهرس بعد المباراة مباشرة.

عند إنشاء regexp ، يكون “lastIndex” هو “0”.

لذلك ، المكالمات المتتالية لعودة regexp.exec (str) تتطابق واحدة تلو الأخرى.

مثال (بعلامة g):

let str = 'let varName';

let regexp = /\w+/g;
alert(regexp.lastIndex); // 0 (initially lastIndex=0)

let word1 = regexp.exec(str);
alert(word1[0]); // let (1st word)
alert(regexp.lastIndex); // 3 (position after the match)

let word2 = regexp.exec(str);
alert(word2[0]); // varName (2nd word)
alert(regexp.lastIndex); // 11 (position after the match)

let word3 = regexp.exec(str);
alert(word3); // null (no more matches)
alert(regexp.lastIndex); // 0 (resets at search end)

يتم إرجاع كل مباراة كمصفوفة بمجموعات وخصائص إضافية.

يمكننا الحصول على جميع المباريات في الحلقة:

let str = 'let varName';
let regexp = /\w+/g;

let result;

while (result = regexp.exec(str)) {
  alert( `Found ${result[0]} at position ${result.index}` );
  // Found let at position 0, then
  // Found varName at position 4
}

يعد استخدام regexp.exec بديلاً للطريقةstr.matchAll.

على عكس الطرق الأخرى ، يمكننا تعيين “lastIndex” الخاص بنا لبدء البحث من الموضع المحدد.

على سبيل المثال ، دعنا نجد كلمة ، بدءًا من الموضع 4:

let str = 'let varName = "value"';

let regexp = /\w+/g; // without flag "g", property lastIndex is ignored

regexp.lastIndex = 4;

let word = regexp.exec(str);
alert(word); // varName

أجرينا بحثًا عن النمط: \ w + ، بدءًا من الموضع regexp.lastIndex = 4.

يرجى ملاحظة: يبدأ البحث في الموضع lastIndex ثم يذهب إلى أبعد من ذلك. إذا لم يكن هناك كلمة في الموضع lastIndex ، لكنها موجودة في مكان ما بعدها ، فسيتم العثور عليها:

let str = 'let varName = "value"';

let regexp = /\w+/g;

regexp.lastIndex = 3;

let word = regexp.exec(str);
alert(word[0]); // varName
alert(word.index); // 4

…So ، مع وضع علامة g خاصيةlastIndex تحدد موضع البداية للبحث.

** وضع علامة على “النمط: y” يجعل “regexp.exec” ينظر بالضبط إلى الموضع “lastIndex” ، ليس قبله وليس بعده. **

هذا هو نفس البحث مع العلم y:

let str = 'let varName = "value"';

let regexp = /\w+/y;

regexp.lastIndex = 3;
alert( regexp.exec(str) ); // null (there's a space at position 3, not a word)

regexp.lastIndex = 4;
alert( regexp.exec(str) ); // varName (word at position 4)

كما نرى ، لا يتطابق regexp / \ w + / y في الموضع3 (على عكس العلم g) ، ولكنه يتطابق في الموضع4.

تخيل ، لدينا نص طويل ، ولا يوجد تطابق على الإطلاق. ثم البحث باستخدام العلامة نقش: g سيستمر حتى نهاية النص ، وسيستغرق هذا وقتًا أكثر بكثير من البحث باستخدام العلمنقش: ص.

في مثل هذه المهام مثل التحليل المعجمي ، عادة ما تكون هناك العديد من عمليات البحث في موضع محدد. إن استخدام العلم y هو مفتاح الأداء الجيد.

خريطة الدورة التعليمية

التعليقات

إقرأ هذا قبل أن تضع تعليقًا…
  • إذا كان لديك اقتراحات أو تريد تحسينًا - من فضلك من فضلك إفتح موضوعًا فى جيتهاب أو شارك بنفسك بدلًا من التعليقات.
  • إذا لم تستطع أن تفهم شيئّا فى المقال - وضّح ماهو.
  • إذا كنت تريد عرض كود استخدم عنصر <code> ، وللكثير من السطور استخدم <pre>، ولأكثر من 10 سطور استخدم (plnkr, JSBin, codepen…)