وجود عدة محارف أو أصناف محارف ضمن قوسين مربعين […]
يعني البحث عن أي محرف بينها. سيكمل هذا المقال الغوص في التعابير النمطية بعد أن تطرقنا إلى مقدمة شاملة عنها في المقال السابق بعنوان أساسيات التعابير النمطية في جافاسكربت.
المجموعات
يعني النمط [eao]
البحث عن أيٍّ من المحارف الثلاثة 'a'
أو 'e'
أو 'o'
، ويُدعى هذا النمط بالمجموعة، ويمكن استخدام المجموعات ضمن التعابير النمطية ومع محارف نظامية:
//"op" ثم [t أو m] جد alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top"
لاحظ أنه وعلى الرغم من وجود عدة محارف ضمن المجموعة، فإنها سترتبط بمحرف واحد تمامًا عند إعادة النتيجة، فمثلًا لن يعيد البحث التالي أي نتيجة:
//"la" ثم [o أو i] ثم "V" جد alert( "Voila".match(/V[oi]la/) ); // null, no matches
سيبحث النمط عن:
-
V
ثم أحد الحرفين[oi]
. -
ثم
la
. -
لذا ستكون النتيجة إما
Vola
أوVila
، والنصان غير موجودين.
المجالات
يمكن أن تضم الأقواس المربعة مجالات من المحارف، مثل المجال [a-z]
، الذي يحدد المحارف بين a
وz
، أو المجال [0-5]
الذي يحدد الأرقام بين 0
و5
، وسنبحث في المثال التالي عن "x"
متبوعًا برقمين أو حرفين من A
إلى F
:
alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF
ستجد مجالين ضمن الأقواس المربعة [A-F0-9]
، وسنبحث عن عدد من 0 إلى 9 أو حرف من A إلى F، ويمكن البحث عن أحرف بالحالة الصغيرة بإضافة المجال a-f
، بحيث يصبح النمط [A-F0-9a-f]
أو باستخدام الراية i
، كما يمكن استخدام أصناف المحارف داخل الأقواس المربعة، فلو أردنا مثلًا البحث عن محرف كلمة أو شرطة قصيرة، فستكون المجموعة المناسبة هي [-w\]
، ويمكن الجمع أيضًا بين أكثر من صنف محارف، مثل المجموعة [s\d\]
، التي تعني البحث عن محرف فراغ أو رقم
انتبه إلى أن أصناف المحارف هي اختصارات لمجموعات محددة من المحارف، فمثلًا:
-
d\
: هي نفسها المجموعة[9-0]
. -
w\
: هي نفسها المجموعة[a-zA-Z0-9]
. -
s\
: هي نفسها المجموعة[t\n\v\f\r\ ]
، بالإضافة إلى بعض محارف فراغ Unicode الخاصة.
مثال: محرف الكلمة w\ للغات متعددة
يمكن لصنف المحارف w\
، كونه اختصارًا للنمط [a-zA-Z0-9]
، أن يجد المحارف العربية أو الصينية وغيرها، لذلك يمكننا كتابة أنماط من التعابير لإيجاد محارف في أي لغة باستخدام خصائص الترميز Unicode مثل التعبير النمطي التالي:
[{p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C\]
ولنفسر الآن هذا النمط، حيث ننشئ فيه مجموعةً خاصةً بنا تتضمن محارف لها خصائص Unicode التالية:
-
Alpha
: للأحرف. -
M
: للعلامات فوق الأحرف. -
Nd
: للأعداد بالنظام العشري. -
Pc
: للشرطة السفلية (_) والمحارف المشابهة. -
Join_C
: للمحارف الخاصة200c
و200d
التي تستخدم في لغات غير لاتينية، مثل العربية.
إليك مثالًا:
let regexp = /[\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]/gu; let str = `Hi 你好 12`; // جد كل الأحرف والأرقام: alert( str.match(regexp) ); // H,i,你,好,1,2
يمكن بالطبع تعديل هذه النمط بإضافة خصائص جديدة أو إزالتها، وسنفصّل في هذا الخصائص لاحقًا.
انتبه إلى أن خصائص يونيكود Unicode أي p{...}
غير مدعومة في متصفح إنترنت إكسبلورر IE، فلا يدعم متصفح IE خصائص Unicode، فإذا احتجنا إليها فيمكننا استخدام المكتبة XRegExp، ومن الممكن أيضًا استخدام مجالات لأحرف اللغة المطلوبة، مثل المجال [ا-ي] في اللغة العربية.
مجالات الاستثناء
ستجد أيضًا مجالات لاستثناء محارف معينة تبدو بالشكل […^]
، فهي معلّمة بالمحرف ^
في البداية، وتطابق أي محرف عدا المحارف المعطاة، وإليك بعض الأمثلة:
-
[aeyo^]
: أي محرف عدا المحارف'a'
أو'e'
أو'y'
أو'o'
. -
[0-9^]
: أي محرف عدا الأرقام، لها وظيفة الصنفD\
. -
[s\^]
: أي محرف لا يمثل محرف فراغ.
يبحث المثال التالي عن أي محارف عدا الأحرف أو الأرقام أو الفراغات:
alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // @ and .
التجاوز عند استخدام […]
رأينا سابقًا أننا نتجاوز (نهرِّب) الوظيفة الخاصة لمحرف باستخدام الشرطة المعكوسة .\
، وإذا أردنا البحث عن الشرطة المعكوسة بذاتها نكررها مرتين \\
، ويمكن استخدام معظم المحارف الخاصة ضمن الأقواس المربعة دون الحاجة إلى تجاوزها:
-
لاتحتاج الرموز
. + ( )
إلى تجاوز. -
لا يحدث تجاوز للشرطة
-
في بداية ونهاية النص، أي عندما لا تحدد مجالًا. -
يحدث تجاوز للعلامة
^
في بداية النص فقط، عندما تعني الاستثناء. -
يحدث تجاوز دائم لقوس الإغلاق المربع
[
، إن أردنا البحث عنه بحد ذاته.
وبعبارة أخرى يُسمح باستخدام المحارف الخاصة جميعها دون الحاجة للتجاوز؛ إلا عندما تعني شيئًا محددًا ضمن الأقواس المربعة، فالنقطة ضمن الأقواس المربعة تعني نقطة، فمثلًا سيبحث النمط [.,]
مثلًا عن نقطة أو فاصلة.
يبحث النمط [-().^+]
في المثال التالي عن أي محرف من المحارف +().^-
:
// لا حاجة للتجاوز let regexp = /[-().^+]/g; alert( "1 + 2 - 3".match(regexp) ); // تطابق +, -
لكن إذا قررت تجاوز هذه المحارف للاحتياط، فلا مشكلة في ذلك:
// تجاوز كل شيء let regexp = /[\-\(\)\.\^\+]/g; alert( "1 + 2 - 3".match(regexp) ); // سينجح أيضًا +, -
المجالات واستعمال الراية "u"
إذا وجد محرف بصيغة زوج بديل surrogate pair، وهو تفسير بعض الخصائص للمحرف ذي البايتات الأربع، فلا بدّ من استخدام الراية u
للتعامل مع هذه المحارف.
لنبحث مثلًا عن النمط [??]
ضمن النص "?":
alert( '?'.match(/[??]/) ); // [?] سيظهر محرف غريب مثل // جرى البحث بطريقة غير صحيحة وأعاد نصف المحرف فقط
ستكون النتيجة خاطئةً، لأن التعبير النمطي لا يعلم بوجود زوج بديل افتراضيًا، إذ يعتقد محرك التعبير النمطي أن النمط [??]
مكون من أربعة محارف، وليس محرفين:
- الأول هو النصف اليساري من ?.
- الثاني هو النصف اليميني من ?.
- ,الثالث هو النصف اليساري من ?.
- الرابع هو النصف اليميني من ?.
ويمكننا الاطلاع على ترميزها بالشكل التالي:
for(let i=0; i<'??'.length; i++) { alert('??'.charCodeAt(i)); // 55349, 56499, 55349, 56500 };
إذًا سيجد المثال السابق النصف الأيسر فقط من ? ويعرضه، لكن سنحل المشكلة عند إضافة الراية u
:
alert( '?'.match(/[??]/u) ); // ?
ونستخدم الحل نفسه عندما نبحث عن مجال يحوي محارف بأزواج بديلة، مثل [?-?]
، وسينتج خطأً إذا لم نستخدم الراية u
.
'?'.match(/[?-?]/); // خطأ: تعبير نظامي غير صحيح
والسبب أنّ الزوج البديل سيعامل مثل محرفين دون الراية u
، وهكذا سيُفسَّر النمط [?-?]
على الشكل التالي:
[<56500><55349>-<56499><55349>]
حيث يُبدَّل كل زوج بترميزه، وهكذا سيكون المجال 56499-55349
خاطئًا، لأن الرمز النصي 56499
لبداية المجال أكبر من الرمز النصي 55349
لنهايته، وهذا هو سبب الخطأ، وسيعمل النمط بشكل صحيح بوجود الراية u
:
// ? إلى ? البحث عن محارف من alert( '?'.match(/[?-?]/u) ); // ?
ترجمة -وبتصرف- للفصل Sets and Ranges من سلسلة The Moden JavaScript Tutorial.
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.