تقنية

اختبار RegExp المتكرر: لماذا تتبدل النتيجة والنص ثابت؟

نداءات A الثلاثة على ab: مؤشر البدء صفر ثم2 ثم صفر؛ الأجوبة صحيح وخطأ وصحيح.
النص نفسه في الصفوف الثلاثة؛ المثلث يبين الموضع قبل النداء.

مع العلم g يحتفظ التعبير بموضع البحث في lastIndex؛ لذلك لا يكفي تثبيت النص لضمان بدء كل اختبار من أوله. [1]

الخلاصة السريعة

  • في A أعطى النص ab النتائج صحيح ثم خطأ ثم صحيح.
  • أعطت B بلا g ثلاث نتائج صحيحة؛ وكذلك C مع التصفير قبل كل نداء.
  • تغير النص إلى ab! في D، لكن النداء الثاني بقي فاشلا.
  • أعطت E على ab-ab نجاحين ثم فشلا؛ سجلنا الموضع بعد كل نداء.

سجل ما قبل النداء وما بعده

آخر موضع ليس جوابا منطقيا: lastIndex يحدد بداية البحث التالي، بينما test يعيد صحيحا أو خطأ. [2]

صممنا خمس نسخ صغيرة بالأحرف a وb، وعلامة تعجب أو شرطة في اثنتين منها. في كل نسخة نحتفظ بكائن التعبير نفسه لثلاثة نداءات، وننشئ كائنا جديدا عند الانتقال إلى نسخة أخرى. لا توجد في عينتنا مطابقة فارغة أو أحرف خارج هذه السلاسل القصيرة.

نسجل أربع خانات لكل نداء: النص، والموضع قبله، والجواب، والموضع بعده. نقرأ الخانة الأولى من النص الفعلي الذي مررناه، لا من اسم المتغير. سنسمي النسخ A إلى E حتى لا نخلط تغيير العلم بتغيير النص أو بتغيير الموضع يدويا.

شغل النسخ الخمس كاملة

نفذ الشيفرة التالية؛ كل سطر مطبوع يسجل اسم النسخة والنص والموضع السابق والجواب والموضع اللاحق. [1] [2]

شغلنا المقطع في Node 24.19.0 وفي Edge 155.0.4283.45. اتفقت البيئتان في القراءات الخمس عشرة. في الجدول نكتب «صحيح» مقابل true و«خطأ» مقابل false؛ كلمة صحيح تصف جواب المطابقة، ولا تحكم على سلامة برنامج أكبر.

function trace(label, re, inputs, reset = false) {
  for (const input of inputs) {
    if (reset) re.lastIndex = 0;
    const before = re.lastIndex;
    const found = re.test(input);
    console.log(label, input, before, found, re.lastIndex);
  }
}
trace("A", /ab/g, ["ab", "ab", "ab"]);
trace("B", /ab/, ["ab", "ab", "ab"]);
trace("C", /ab/g, ["ab", "ab", "ab"], true);
trace("D", /ab/g, ["ab", "ab!", "ab!"]);
trace("E", /ab/g, ["ab-ab", "ab-ab", "ab-ab"]);
النسخةالنداءالنصقبلالجواببعد
A1ab0صحيح2
A2ab2خطأ0
A3ab0صحيح2
B1ab0صحيح0
B2ab0صحيح0
B3ab0صحيح0
C1ab0صحيح2
C2ab0صحيح2
C3ab0صحيح2
D1ab0صحيح2
D2ab!2خطأ0
D3ab!0صحيح2
E1ab-ab0صحيح2
E2ab-ab2صحيح5
E3ab-ab5خطأ0

اقرأ A دون تغيير النص

بدأت A عند الصفر على ab. سجل النداء الأول صحيحا وانتهى عند 2، ثم بدأ الثاني من 2 وسجل خطأ وعاد إلى صفر. بدأ الثالث من الصفر من جديد، وسجل صحيحا وانتهى عند 2. السلسلة ذات الحرفين نفسها مطبوعة في الصفوف الثلاثة.

في التعبير العالمي يعيد الفشل lastIndex إلى الصفر؛ والنجاح يحتفظ بالحالة حتى إن تغير النص التالي. [1]

لو احتفظنا بعمود الأجوبة وحده لرأينا تناوبا، لكننا لن نعرف أين بدأ كل نداء. لهذا يكرر الرسم شريط الحرفين ثلاث مرات ويضع المؤشر السابق بجانب كل قراءة. عند النداء الثاني يقع المؤشر عند نهاية شريطنا، مع أن الحرفين ما زالا ظاهرين إلى يساره.

قارن B وC ثم غير النص في D

في B استعملنا /ab/ بلا العلم g؛ أعطت النداءات الثلاثة صحيحا، وبقي الموضع صفرا قبل كل منها وبعده. في C استعملنا /ab/g مع تعيين الصفر قبل كل نداء؛ أعطت الثلاثة صحيحا أيضا، لكن الموضع بعدها كان 2. تطابقت الأجوبة واختلف العمود الأخير.

يمكن تعيين lastIndex مباشرة؛ لتجربة مدخلات مستقلة أعده إلى الصفر قبل كل اختبار عالمي. [2]

يعرض السطر C ذلك التعيين داخل الدالة قبل تسجيل خانة «قبل». لذلك تعني أصفاره الثلاثة موضع البدء بعد تدخلنا، ولا تعني أن النداء السابق انتهى بصفر. هذا التفصيل يفسر لماذا نكتب طريقة القياس بجوار النتيجة.

بدأت D بالنص ab ثم استعملت ab! مرتين. نجح الأول وانتهى عند 2؛ بدأ الثاني من الموضع نفسه على النص الأطول وفشل وعاد إلى صفر. نجح الثالث على ab! من الصفر. لم نبدل الكائن بين هذه النداءات، ولم تضف علامة التعجب زوجا جديدا من الحرفين.

خمس بطاقات A إلى E تعرض نصوصها الثلاثة وحركة الموضع وجواب كل نداء؛ C يبدأ بعد التصفير الصريح.
الأسهم من الموضع السابق إلى اللاحق؛ في C سجلنا السابق بعد التصفير.

تابع موضعين في E

في E كررنا ab-ab ثلاث مرات. سجلنا صحيحا من صفر إلى 2، ثم صحيحا من 2 إلى 5، ثم خطأ من 5 إلى صفر. يختلف هذا عن تناوب A: لدينا هنا نسختان ظاهرتان من ab تفصل بينهما الشرطة، لا سلسلة الحرفين وحدها.

ضع قراءتي النجاح بجانب موضعي النص: تنتهي الأولى بعد b الأولى، والثانية بعد b الأخيرة. إذا توقعت أن كل نداءين يتناوبان بين صحيح وخطأ، فإن صف E الثاني وحده ينقض ذلك التوقع في بياناتنا. لا تجعل النمط الذي رأيته في A قاعدة لكل سلسلة.

اختر السجل الموافق لسؤالك

إذا كان السؤال المحلي «هل يوجد ab في كل مدخل مستقل؟»، فإن B أو C أعطتا في عينتنا ثلاث إجابات صحيحة، مع اختلاف أثر الموضع المطبوع. أما E فاحتفظت بالموضع بين النداءات وأظهرت موضعين مختلفين قبل الفشل. سجل الاختيار مع الشيفرة التي نفذتها.

لا تختبر هذه البيانات مطابقة النص كله أو سرعة المحرك أو معالجة أنماط يقدمها مستخدم. كما لا تعمم أرقام المواضع على أحرف لم نضعها في العينة. النتيجة القابلة للمراجعة هنا محددة: خمس نسخ، وثلاثة نداءات في كل منها، وكل نص وموضع وجواب ظاهر في الجدول.

المراجع

  1. MDN: RegExp.test
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
  2. MDN: RegExp.lastIndex
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex
أُعد بمساعدة الذكاء الاصطناعي؛ مراجعة آلية دون اعتماد بشري أو مهني. تاريخ الإعداد13 أكتوبر2026.

أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي وراجعته أدوات ذكاء اصطناعي. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.