اذهب إلى المحتوى

المحددات الكمية وأنماط استخدامها في التعابير النمطية


ابراهيم الخضور

لنفترض أنّ لدينا النص التالي 67-45-123-(903)7+، وأننا نريد إيجاد كل الأعداد الموجودة ضمنه، سنحتاج هنا إلى أعداد كاملة، مثل 7 و903 و123 و45 و67، لا إلى كل رقم بمفرده، حيث يتألف العدد من رقم واحد أو تتابعٍ لأرقام d\، ولتحديد عدد الأرقام التي نحتاجها سنستخدم محددًا كميًا أو مكممًا quantifier.

محدد الكمية {n}

إنّ أبسط المحددات الكمية هو رقم ضمن أقواس معقوصة {n}، حيث يضاف المكمم إلى المحرف أو صنف المحرف أو الأقواس المربعة وغيرها؛ ليحدد العدد الذي نحتاجه منها، وللمكممات بعض الأشكال المتقدمة التي سنستعرض أمثلةً عنها:

  • العدد الدقيق: مثل {5}، والذي يحدد العدد الدقيق من المحارف التي نحتاجها، فمثلًا يحدد {5}d خمسة أرقام تمامًا، كما لو كتبنا d\d\d\d\d\، ويعرض المثال التالي كيف نبحث عن خمسة أرقام متتالية:
alert( "I'm 12345 years old".match(/\d{5}/) ); //  "12345"

ويمكن إضافة محرف حد الكلمة b\ لنستثني الأرقام الأطول.

  • المجال: مثل {3,5}، ويحدد الأعداد التي تضم من 3 إلى 5 أرقام، ولإيجاد ذلك توضع حدود المجال ضمن أقواس معقوصة:
alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"`

يمكننا تجاهل الحد الأعلى ليصبح التعبير على الشكل {,d{3\، وسيبحث عن أعداد مؤلفة من ثلاثة أرقام أو أكثر:

alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) );// "345678"`

لنعد الآن إلى النص 67-45-123-(903)7+، حيث يتألف العدد من رقم واحد أو من تتابعٍ لأرقام في صف، فالتعبير النمطي المناسب هو {,d{1\:

let str = "+7(903)-123-45-67";

let numbers = str.match(/\d{1,}/g);

alert(numbers); // 7,903,123,45,67

اختصارات المحددات الكمية

لمعظم المكممات اختصارات، وهي:

  • +: يعني "واحد أو أكثر" مرة، تمامًا مثل النمط {,1}، إذ يبحث النمط +d\ عن الأعداد:
let str = "+7(903)-123-45-67";
alert( str.match(/\d+/g) ); // 7,903,123,45,67`
  • ?: يعني "صفر أو واحد" مرة، تمامًا مثل النمط {0,1}، أي يجعل الرمز اختياريًا، إذ يبحث النمط ou?r مثلًا عن المحرف o متبوعًا بمحرف u واحد أو غير متبوع به، ومن ثم المحرف r، لنبحث عن الكلمتين color أو colour:
let str = "Should I write color or colour?";
alert( str.match(/colou?r/g) ); // color, colour
  • *: يعني "صفر أو أكثر"، تمامًا مثل النمط {,0}، أي يبحث عن عدم وجود محرف أو تكراره مرةً واحدةً أو أكثر، إذ يبحث النمط *d0\ مثلًا عن رقم متبوع بأي تكرار للمحرف 0 (عدم وجوده أو تكراره مرةً أو عدة مرات):
alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1`
alert( "100 10 1".match(/\d0+/g) ); // 100, 10 //  لا تطابق مع 1 لأن النمط 0+ سيتطلب أكثر من صفر

أمثلة أكثر

تستخدم المكممات كثيرًا، وتُعدّ البنية الرئيسية للتعابير النمطية المعقدة، وسنطلع على بعض الأمثلة.

التعبير النمطي للكسور العشرية (عدد بفاصلة عشرية)

ويعطى بالشكل +d+\.\d\، إليك مثالًا:

alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345

التعبير النمطي لفتح وسم HTML لا يحوي سمات مثل أو

  1. الطريقة الأبسط: a-z]+>/i]>/
alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>

يبحث التعبير عن المحرف '>' يتبعه حرف لاتيني أو أكثر، ثم المحرف '<'.

  1. الطريق المحسنة: a-z][a-z0-9]*>/i]>/: إذ يمكن أن يحتوي وسم HTML -مثلما تنص المعايير- على رقم في أي موقع من الاسم، عدا بدايته مثل <h1>.
alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>

التعبير النمطي لفتح أو إغلاق وسم HTML لا يحوي سمات

استخدم التعبير التالي: a-z][a-z0-9]\*>/i]?/\>/، حيث وضعنا شرطةً مائلةً اختياريةً ?/ قرب بداية النمط، وكان لابد من تجاوزها بشرطة معكوسة، وإلا فستعتقد JavaScript أنها نهاية النمط.

alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>

لاحظ أنه لكتابة تعابير نمطية أكثر دقةً لا بدّ من تعقيد التعبير أكثر، فيمكن أن ترى بأن القاعدة المشتركة بين تلك الأمثلة هي أنّ الدقة تأتي من تعقيد التعبير وطوله، ففي وسوم HTML كان يمكننا استخدام التعبير <+w\>، لكن التعبير الذي استخدمناه هو الأصلح؛ بما يتوافق مع تقييدات التسمية وقواعدها في HTML.

هل يمكن استخدام <+w\> أم يجب استخدام النمط <‎[a-z][a-z0-9]*‎>؟

يُقبَل استخدام كلا النمطين في الواقع العملي، ويعتمد اختيارنا على قدرتنا على التعامل مع التطابقات الناتجة عن البحث، وصعوبة استخلاصها بطرق أخرى.

مكممات البحث الجشعة والكسولة

تبدو المكممات Quantifiers بسيطة الاستخدام للوهلة الأولى، لكنها قد تغدو مربكةً عند استخدامها، لذلك لا بدّ من فهم آلية البحث جيدًا إذا خططنا للبحث عن أشياء أكثر تعقيدًا من /+d\/، لنلق نظرةً على المهمة التالية مثلًا:

لدينا نص ما ونريد استبدال الإشارتين «...» بإشارتي التنصيص "..."، لأنها مفضلة في تنسيقات الطباعة والكتابة في بلدان عدة، أي يجب أن يصبح النص "مرحبًا أحمد" مثلًا بالشكل «مرحبًا أحمد»، وسنجد أيضًا إشارتي التنصيص „!Witam, świat” في اللغة البولندية، أو الإشارتين 「你好,世界」 في اللغة الصينية، لكننا سنختار الإشارتين «...» فقط في مهمتنا.

ستكون الخطوة الأولى تحديد النصوص الموضوعة ضمن إشارتي التنصيص، ثم استبدالهما، وقد يبدو التعبير النمطي التالي g/"+."/، والذي يعني (إشارة تنصيص ثم شيء ما مكرر ثم إشارة تنصيص أخرى) مناسبًا، لكنه ليس كذلك.

انظر إلى المثال التالي:

let regexp = /".+"/g;

let str = 'a "witch" and her "broom" is one';

alert( str.match(regexp) ); // "witch" and her "broom"

لم يعمل النمط كما هو مطلوب! فبدلًا من إيجاد الكلمتين "witch" و"broom"، وجد العبارة التالية:"witch" and her "broom".

البحث الجشع Greedy search

يتبع محرك التعابير النمطية الخوارزمية التالية في إيجاد التطابقات:

  • من أجل كل موقع في النص:
  • يحاول إيجاد التطابق عند هذا الموقع.
  • إذا لم يجد تطابقًا فسينتقل إلى الموقع التالي.

لكن هذه الكلمات غير قادرة على وصف سبب فشل التعبير بدقة، لذلك سنفصل آلية البحث عن النمط "+.":

الخطوة الأولى، يحاول المحرك إيجاد المحرف الأول من النمط "عند الموقع 0 من النص a "witch" and her "broom" is one، لكنه بدلًا من ذلك سيجد المحرف a، لذلك سيتابع إلى الموقع التالي ويحاول إيجاد أول محارف النمط وسيخفق ثانيةً، وأخيرًا سيجد تطابقًا في الموقع الثالث (الموقع 2).

greedy_step1_01.png

الخطوة الثانية، يجد المحرك المحرف الأول ويتابع لإيجاد بقية محارف النمط، ويحاول أن يكتشف فيما لو تطابق بقية النص مع المحارف الباقية من النمط "+.، وسيكون المحرف التالي في النمط هو النقطة .، التي تشير إلى أي محرف عدا محرف السطر الجديد، لذلك ستجد التطابق مع الحرف 'w'.

greedy_step2_02.png

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

greedy_step3_03.png

الخطوة الرابعة، سينتهي المحرك من تكرار المحرف . ويحاول إيجاد المحرف التالي من النمط -وهي إشارة التنصيص "-، وهنا تظهر المشكلة فقد انتهى النص ولم يعد هناك المزيد من المحارف للبحث ضمنها، عندها سيفهم المحرك أنه ضم الكثير من المحارف .+، وسيبدأ بالتراجع، حيث يختصر نتيجة التطابق التي ولّدها المكمم بمقدار محرف إلى الخلف؛ مفترضًا أن المحارف ستنتهي قبل انتهاء النص بمحرف واحد، ثم يحاول إيجاد بقية محارف النمط انطلاقًا من هذا الموقع، وسينهي المحرك البحث إذا وجد المحرف، لكنه سيجد المحرف 'e'، وبالتالي لن تنتهي العملية.

greedy_step4_04.png

الخطوة الخامسة، سيقلل المحرك عدد المحارف الناتجة عن تكرار النقطة بمحرف واحد أيضًا، إلى أن يجد التطابق مع آخر محارف النمط '"' حتى يجده.

greedy_step5_05.png

الخطوة السادسة، سيكتمل البحث عند إيجاد التطابق.

greedy_step6_06.png

الخطوة السابعة، وهكذا ستكون النتيجة هي "witch" and her "broom".

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

يكرَّر المكمم في النمط الموسَّع -افتراضيًا- أكبر عدد ممكن من المرات، حيث يضيف المحرك القدر الأكبر من المحارف التي تتطابق مع +.، ثم يختصر النتيجة محرفًا تلو الآخر.

النمط الكسول Lazy mode

النمط الكسول أو المحدود هو نمط معاكس للنمط الموَّسع أو الجشع، ويعني أقل تكرار للمحارف، ويمكن أن نختار هذا النمط بوضع إشارة الاستفهام ? بعد المكمم حيث يصبح بالشكل ?* أو ?+ أو حتى ?? لــ?، ولنوضح الأمر علينا معرفة أن إشارة الاستفهام ? هي مكمم بحد ذاتها (صفر أو واحد)، وعندما تُضاف بعد مكمم آخر فسيصبح لها معنىً آخر، وهو تحويل نمط البحث إلى النمط المحدود الكسول، وسيعمل النمط g/"?+."/ في مهمتنا السابقة بالشكل الصحيح:

let regexp = /".+?"/g;

let str = 'a "witch" and her "broom" is one';

alert( str.match(regexp) ); // "witch", "broom"

ولفهم التغيّر بوضوح سنتعقب عملية البحث خطوةً خطوةَ:

الخطوة الأولى، تبقى الخطوة الأولى نفسها، وهي إيجاد المحرف '"' في الموقع الثالث من النص.

lazy_step1_01.png

الخطوة الثانية، وسيجد المحرك في الخطوة الثانية ما يطابق المحرف '.'.

lazy_step2_08.png

الخطوة الثالثة، سيظهر الاختلاف الآن، حيث لا يحاول المحرك في النمط المحدود إيجاد تطابق مع ما تمثله النقطة مرةً أخرى، بل يتوقف ويحاول إيجاد تطابقات مع بقية محارف النمط (أي '"') مباشرةً، وسيتوقف البحث عن النمط إذا وجد تطابقًا، لكنه سيجد الحرف i بدلًا منه.

lazy_step3_09.png

الخطوة الرابعة، سيزيد بعد ذلك محرك التعبير النمطي عدد التكرارات لمحرف النقطة مرةً واحدةً، ثم يحاول مطابقة بقية النمط، لكنه سيفشل ثانيةً، وسيزيد عدد مرات التكرار مرةً أخرى وأخرى…

lazy_step4_10.png

الخطوة الخامسة، سيتوقف البحث عندما يجد التطابق مع المحرف '"'.

lazy_step5_11.png

الخطوة السادسة، يبدأ البحث الجديد، نظرًا لوجود الراية g، من الموقع الذي انتهى عنده البحث السابق، وسيجد النتيجة الثانية.

lazy_step6_12.png

يعمل النمط الكسول بشكل مشابه للمكممات ?* و??، حيث يزيد محرك التعبير النمطي عدد التكرارات إذا لم يجد تطابقًا مع بقية محارف النمط في الموقع المُعطى.

يُفعّل النمط الكسول للمكممات إذا تبعها المحرف ?، وإلا فستبقى في النمط الموّسع الجشع، إليك مثالًا:

alert( "123 456".match(/\d+ \d+?/) ); // 123 4
  1. يحاول النمط +d\ إيجاد أكبر عدد ممكن من الأعداد (نمط موسّع)، لذلك سيجد 123 ويتوقف، لأن المحرف التالي سيكون الفراغ ' '.
  2. سيجد المحرك المحرف التالي في النمط وهو الفراغ ' '.
  3. يحاول إيجاد الأعداد التالية وفقًا للنمط ?+d\ حيث يكون المكمم محدودًا، وسيجد العدد 4 ثم يتحقق من وجود بقية محارف النمط بعده، لكن محارف النمط قد انتهت.

لا يكرر النمط الكسول أي شيء دون حاجة إلى ذلك، لذا سينتهي البحث بالنتيجة 4 123.

لاحظ، تحسن محركات التعابير النمطية الحديثة خوارزميات البحث الداخلية لتعمل بسرعة أكبر، لذلك قد تعمل بطريقة مختلفة قليلًا عما وصفناه سابقًا، ولن نحتاج إلى معرفة تفاصيل الخوارزمية المحسَّنة عند كتابة التعابير النمطية وفهمها، لأنها تعمل داخليًا، وبما أن التعابير المعقدة صعبة التحسين، فسيجري البحث وفق الخطوات التي وصفناها سابقًا تمامًا.

مقاربة بديلة

نجد عادةً عند استخدام التعابير النمطية عدة طرق لتنفيذ الشيء نفسه، إذ يمكن في حالتنا السابقة إيجاد إشارات التنصيص دون الحاجة إلى البحث المحدود، بل من خلال النمط "+[^"]"

let regexp = /"[^"]+"/g;

let str = 'a "witch" and her "broom" is one';

alert( str.match(regexp) ); // "witch", "broom"

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

مثال عن إخفاق المكمم الكسول ونجاح الأسلوب البديل

لنحاول مثلًا إيجاد رابط من الشكل <a href="..." class="doc"‎> بحيث يصلح لأي عنوان href، فما هو التعبير النمطي الذي سنستخدمه؟

قد تكون الفكرة الأولى هي: a href=".*" class="doc">/g>/، وسنتحقق منها:

let str = '...<a href="link" class="doc">...';
let regexp = /<a href=".*" class="doc">/g;

// !عملت
alert( str.match(regexp) ); // <a href="link" class="doc">

ستعمل هذه الفكرة، لكن دعونا نتحقق منها عند وجود عدة روابط في النص:

let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
let regexp = /<a href=".*" class="doc">/g;

// حصلنا على رابطين في نتيجة واحدة
alert( str.match(regexp) ); // <a href="link1" class="doc">... <a href="link2" class="doc">

النتيجة خاطئة، لأنّ المكمم *. ضمّ الكثير من المحارف، وسيكون التطابق مشابهًا للوصف التالي:

<a href="....................................." class="doc">
<a href="link1" class="doc">... <a href="link2" class="doc">

لنُعدِّل النمط بجعل المكمم كسولًا ( ?*.):

let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
let regexp = /<a href=".*?" class="doc">/g;

// Works!
alert( str.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc">

سينجح الأمر وسيجد الرابطين:

<a href="....." class="doc">    <a href="....." class="doc">
<a href="link1" class="doc">... <a href="link2" class="doc">

لنختبر ذلك مع نص آخر:

let str = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
let regexp = /<a href=".*?" class="doc">/g;

// أخفق أيضًا
alert( str.match(regexp) ); // <a href="link1" class="wrong">... <p style="" class="doc">

لقد أخفق البحث مجددًا، فقد طابق البحث الكثير من محارف النص بما فيها <p>، فما السبب؟

إليك ما حدث:

  1. يجد محرك التعبير النمطي المحارف <"=a href> بدايةً.
  2. ثم يبحث عن المكمم المحدود ?*.، الذي يأخذ محرفًا ويتحقق من وجود تطابق مع بقية أحرف النمط "class="doc "، فلا يجد شيئًا.
  3. ثم يضيف محرفًا إلى نتيجة النمط ?*. ويستمر بالإضافة إلى أن يصل إلى "class="doc "، لكن المشكلة أن ما وجده سيكون خارج حدود الرابط <...a> وضمن وسم مختلف <P>.

إليك وصفًا لما حدث:

<a href="..................................." class="doc">
<a href="link1" class="wrong">... <p style="" class="doc">

لاحظ إخفاق كل من البحث الجشع والكسول في المهمة، لكن سيُنفذ النمط "*[^"]"=href المطلوب في حالتنا، لأنه سيبحث عن المحارف ضمن السمة href إلى أن يجد أقرب إشارة تنصيص، وهذا ما نريده.

إليك مثالًا:

let str1 = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
let str2 = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
let regexp = /<a href="[^"]*" class="doc">/g;

// Works!
alert( str1.match(regexp) ); // null, لا تطابق وهذا صحيح
alert( str2.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc">

الخلاصة

للمكممات Quantifiers نمطان للعمل:

  • الواسع الجشع Greedy: وهو الخيار الافتراضي الذي يحاول فيه محرك التعبير النمطي تكرار المحرف المُحصى أكبر عدد ممكن من المرات، فالنمط +d\ مثلًا سيستهلك كل الأرقام الممكنة، وعندما لا يعود قادرًا على إضافة المزيد من المحارف سيتابع مطابقة بقية أحرف النمط، فإذا لم يجد تطابقًا فسيقلل عدد مرات التكرار مرةً واحدةً -يتراجع- ويحاول مجددًا.
  • المحدود الكسول Lazy: ويُمكَّن بإضافة إشارة الاستفهام بعد المكمم، حيث يحاول المحرك إيجاد تطابق مع بقية محارف النمط قبل تكرار البحث عن المحرف المُحصى.

ويمكن استخدام بحث موّسع ومعدّل بدقة وفق النمط "[^"]+" بديلًا عن الأسلوبين.

مهام لإنجازها

إيجاد ثلاث نقاط متتابعة أو أكثر

اكتب نمطًا للبحث عن ثلاث نقاط متتابعة أو أكثر

let regexp = /your regexp/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....

الحل:

let regexp = /\.{3,}/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....

تذكر أن النقطة . محرف خاص ولابد من تجاوزه وحشر النمط .\.

تحديد الألوان في HTML

أنشئ تعبيرًا نمطيًا للبحث عن ألوان HTML المكتوبة على الشكل ABCDEF#، ابحث أولًا عن المحرف # تليه 6 محارف لأرقام ستة عشرية، إليك مثالًا:

let regexp = /...your regexp.../

let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678";

alert( str.match(regexp) )  // #121212,#AA00ef
اقتباس

ملاحظة: لن نبحث في هذه المهمة عن تنسيقات لونية مثل ‎#123 أو (rgb(1,2,3.

الحل:

علينا أن نبحث عن المحرف # متبوعًا بستة محارف ست عشرية. يمكن وصف المحرف الست عشري وفق النمط [0‎-9a-fA-F]، أو وفق النمط [‎0-9a-f] عند استخدام الراية i. يمكننا عندئذ البحث عن ستة محارف ست عشرية باستخدام المكمم {6}. بالنتيجة سيكون التعبير النمطي المناسب من الشكل:

/#[a-f0-9]{6}/gi

إليك شيفرة الحل:

let regexp = /#[a-f0-9]{6}/gi;

let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2"

alert( str.match(regexp) );  // #121212,#AA00ef

المشكلة في هذا الحل أن التعبير يطابق سلسلة طويلة أكثر حتى لو كانت أكثر من 6 محارف مثل:

alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456

يمكن حل هذه المشكلة بإضافة ‎\b لنهاية التعبير:

// لون
alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456

// ليس لون
alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null

إيجاد تطابق مع النمط /?+d+? d/

ما نتيجة التطابق في المثال الآتي:

alert( "123 456".match(/\d+? \d+?/g) ); // ?

الحل: النتيجة هي 4 123.

يحاول النمط الكسول ‎d+?‎\ أقل عدد ممكن من الأرقام لكنه سيصل إلى محرف المسافة الفارغة وبالتالي سيأخذ فقط 123، ثم يأخذ النمط الثاني ‎d+?‎\ رقمًا واحدًا فقط ويكتفي.

إيجاد تعليقات HTML

أوجد كل التعليقات في النص التالي:

let regexp = /your regexp/g;

let str = `... <!-- My -- comment
 test --> ..  <!----> ..
`;

alert( str.match(regexp) ); // '<!-- My -- comment \n test -->', '<!---->'

الحل:

علينا إيجاد نمط بداية التعليق --!> ثم نأخذ المحارف اللاحقة له حتى نصل إلى نمط نهاية التعليق <--

إذًا سيكون النمط من الشكل <--?*.--!> ، حيث يجبر المكمم الكسول المحرف . على التوقف قبل النمط <--. نحتاج أيضًا إلى الراية s مع النقطة لكي تستمر في ضم المحارف حتى لو انتقلنا إلى سطر جديد وإلا لن نتمكن من التقاط التعليقات الممتدة على أكثر من سطر.

let regexp = /<!--.*?-->/gs;

let str = `... <!-- My -- comment
 test --> ..  <!----> 
..`;
alert( str.match(regexp) ); // '<!-- My -- comment \n test -->', '<!---->'

إيجاد وسوم HTML

أنشئ تعبيرًا نمطيًا لإيجاد كل وسوم HTML (للبداية والنهاية) مع سماتها.

إليك مثالًا:

let regexp = /your regexp/g;

let str = '<> <a href="/"> <input type="radio" checked> <b>';

alert( str.match(regexp) ); // '<a href="/">', '<input type="radio" checked>', '<b>'

نفترض هنا عدم وجود المحرفين < و> ضمن سمات الوسم، مما يسهل الأمر قليلًا.

الحل

سيكون التعبير النمطي الصحيح من الشكل:

<[^<>]+>

إليك شيفرة الحل:

let regexp = /<[^<>]+>/g;

let str = '<> <a href="/"> <input type="radio" checked> <b>';

alert( str.match(regexp) ); // '<a href="/">', '<input type="radio" checked>', '<b>'

ترجمة -وبتصرف- للفصلين َQuntifiers +,*,? And {n} وَGreedy and Lazy Quantifiers من سلسلة The Moden JavaScript Tutorial.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

بتاريخ On 30‏/9‏/2023 at 19:09 قال Anass Ghilmi:

thanks

but url is not work

else if you delete: http://xn--https-cdhh4euc/

مرحبًا @Anass Ghilmi، يسعدنا اهتمامك بالمحتوى الذي ننشره.

في الواقع تم التأكد من الرابط الخاص بالمقال وهو سليم، فهل يمكنك توضيح أي رابط هو الذي لا يعمل لو سمحت؟!

رابط هذا التعليق
شارك على الشبكات الإجتماعية



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...