المسارات
/
JavaScript
JavaScript
/
المنهج
/
التعبيرات النمطية
ال

التعبيرات النمطية في JavaScript

9 تمارين

نبذة عن التعبيرات النمطية

التعبيرات النمطية في JavaScript

التعبير النمطي Regular Expression (أو Regex) هو تسلسل من المحارف يمكننا استخدامه لاستهداف عناصر معيّنة في السلاسل النصية والتعامل معها. ومن ثَمّ يمكننا:

  • البحث عن نص داخل سلسلة نصية
  • الاستبدال داخل سلسلة نصية
  • استخراج المعلومات من سلسلة نصية

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

💡 صيغة التعبيرات النمطية في JavaScript جزء من معيار ECMA-262 الخاص باللغة. وهذا يعني أنك لست بحاجة إلى القلق بشأن التوافق مع متصفح بعينه.

كيفية إنشاء التعبيرات النمطية

في JavaScript، تُكتب التعبيرات النمطية في الغالب بالصيغة /pattern/modifiers، حيث يمثّل 'pattern' التعبير النمطي الأساسي، و'modifiers' سلسلة من المحارف يمكننا إضافتها للإشارة إلى خيارات خاصة (مثل قدرات خارقة).

ومع ذلك، لدينا طريقتان لإنشاء تعبير نمطي:

  1. التعبير النمطي الحرفي:
const regex = /[a-z]/;
  1. البانية RegExp:
const regex = new RegExp('[a-z]');

في كلتا الحالتين، يُنشئ JavaScript كائنًا من التعبير النمطي. ويُوصى باستخدام أنماط غير قابلة للتغيير مع الصيغة الحرفية كوضع افتراضي.

يمكن استخدام البانية RegExp في الحالات التي سيتغيّر فيها التعبير النمطي أو التي لا نعرفه فيها بعد (كما في المدخلات).

🏴‍☠️ الأعلام

تمتلك التعبيرات النمطية قدرات خارقة اختيارية تُسمّى flags وتتيح ميزات إضافية. ويمكن استخدام هذه الأعلام منفردة أو معًا بأي ترتيب، وتُدرج كجزء من التعبير النمطي.

ومن أكثرها استخدامًا:

  • /g - بحث شامل
  • /i - تجاهل حالة الأحرف
  • /m - بحث متعدد الأسطر

إليك مثالًا بسيطًا:

const re = /home/gi;
const str = 'Home, sweet home.';

str.match(re);

// => ["Home", "home"]

يسمح لنا المحرف g بتحليل كل التطابقات الممكنة داخل سلسلة نصية. فمن دون هذه الميزة، كان JavaScript سيستخرج أول تطابق Home فقط.

يتيح لنا العلم الخاص بتجاهل حالة الأحرف /i مرونة أكبر عند البحث عن نمط. فبهذه الطريقة لا يهم إن كان ما نبحث عنه بأحرف UPPERCASE أو lowercase.

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

الدوال الشائعة الاستخدام

عند دمج التعبيرات النمطية مع الدوال المدمجة الحالية في JavaScript، نحصل على وسائل فعّالة للتعامل مع السلاسل النصية واستخراج البيانات منها.

تُعدّ الطريقة test() وسيلة رائعة للبحث ومعرفة ما إذا كانت قيمة هدف موجودة داخل سلسلة نصية معيّنة. وبهذه الطريقة، تُرجع قيمة منطقية، true أو false.

تستخرج الطريقة match() تطابق التعبير النمطي من سلسلة نصية معيّنة، فتُرجع مصفوفة تحتوي على معلومات وتطابقات.

متى نستخدم هذا أو ذاك؟ استخدم test() عندما تريد وسيلة سريعة للتحقق من قيمة داخل سلسلة نصية، واستخدم match() إذا كنت بحاجة إلى استخدام تلك القيمة أو تريد مزيدًا من المعلومات عن التطابق.

Test

تُنفّذ الطريقة test() بحثًا عن تطابق بين تعبير نمطي وسلسلة نصية محدّدة، وتُرجع صحيحًا أو خطأً.

const str = 'It is difficult to test if you have a virus';
const result = /virus$/.test(str);

console.log(result);

// => true

Match

حسنًا، لكن ماذا لو أردنا الحصول على القيم الفعلية لبحث التعبير النمطي؟

فبدلًا من إرجاع قيمة منطقية فقط، نحصل مع الطريقة match() على مصفوفة مفيدة يعتمد محتواها على وجود التطابقات التي عُثر عليها أو غيابها.

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

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';
const regex1 = /someone/;
const regex2 = /happy/;

funnyQuote.match(regex1);
// => ["someone", index: 3, input: "If you see someone crying, ask if it is because of their haircut.", groups: undefined]

funnyQuote.match(regex2);
// => null

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

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';

const regex3 = /if/gi;

funnyQuote.match(regex3);
// => ["If", "if"];

Replace

تتيح لنا الطريقة replace() في JavaScript البحث عن قيمة داخل سلسلة نصية معيّنة واستبدالها بقيمة جديدة.

string.replace(searchValue, newValue);

يمكن أن يكون نمط البحث عن الاستبدال سلسلة نصية واحدة أو تعبيرًا نمطيًا.

let string = 'I like dogs!';
let result = string.replace('dogs', 'cats');

let string = 'I would love to travel to Japan';
let result = string.replace(/Japan/g, 'Hawaii');

علاوة على ذلك، يمكننا تطبيق دالة على موضع الاستبدال لإجراء تغييرات إضافية على كل قيمة.

let text = 'Say hello to the chatbot.';
let result = text.replace(/chatbot|hello/gi, function (word) {
  return word.toUpperCase();
});
// => "Say HELLO to the CHATBOT"

💡 في النهاية، يُعدّ الجمع بين التعبيرات النمطية والطريقة replace() أسلوبًا أكثر ديناميكية لاستبدال العناصر. فقد يكون استخدام سلسلة نصية واحدة محدودًا.

Split

تمثّل الطريقة split() في JavaScript أسلوبًا مختلفًا لاستخدام السلاسل النصية والتعامل معها بواسطة التعبيرات النمطية.

وبهذه الطريقة، سنستخدم التعبير النمطي لتقسيم سلسلة نصية معيّنة بالتعرّف على نمط، مثل str.split(/[,.\s]/). وسيُستخدم هذا النمط بوصفه separator.

const str = 'hello,user.how are.you';

const result = str.split(/[,.\s]/);

console.log(result);
// => ['hello', 'user', 'how', 'are', 'you']

الأداء

فيما يخصّ الأداء، ينشئ كلاهما كائن RegExp. والفرق الرئيسي هو عدد المرات التي يُصرّف فيها التعبير النمطي:

  • مع Regular Expression Literal: مرة واحدة أثناء تحليل الكود وتصريفه الأولي
  • مع صيغة RegExp(): في كل مرة يُنشأ فيها كائن جديد.

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

  1. فهي أقصر ولا تُجبرك على التفكير بأسلوب البواني الشبيهة بالأصناف.
  2. عند استخدام البانية RegExp()، تحتاج أيضًا إلى تخطّي علامات الاقتباس وتخطّي الخطوط المائلة العكسية مرتين. وهذا يجعل التعبيرات النمطية، التي يصعب قراءتها وفهمها بطبيعتها، أكثر صعوبة.
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم التعبيرات النمطية