تعاني التعبيرات النمطية من مشكلة سمعة. يقابلها معظم المطورين لأول مرة عبر سطر غير مقروء مثل ^(?:[a-z0-9!#$%&'*+/=?^_{|}~-]+)*$ فيستنتجون أن الموضوع كله طلاسم. الحقيقة غير ذلك. التعبيرات النمطية لغة صغيرة من نحو خمسة عشر مفهوما، تتراكب فوق بعضها بترتيب منطقي.
يعلمك هذا الدليل تلك المفاهيم بالترتيب الذي يجعلها تثبت في ذهنك. افتح مختبر التعبيرات النمطية في تبويب آخر وجرب كل مثال أثناء القراءة. التعبيرات النمطية تُتعلم بالأصابع لا بالعينين.
ما هو التعبير النمطي؟
التعبير النمطي، أو Regex اختصارا، هو نمط يصف مجموعة من النصوص. تستخدمه لطرح ثلاثة أنواع من الأسئلة:
- المطابقة: هل يطابق هذا النص النمط؟ (التحقق من حقل بريد إلكتروني)
- البحث: أين يظهر النمط في هذا النص؟ (إيجاد كل أرقام الهواتف في مستند)
- الاستبدال: استبدال كل ظهور للنمط بشيء آخر. (إعادة تنسيق آلاف التواريخ دفعة واحدة)
تدعم التعبيرات النمطية كل اللغات والأدوات تقريبا: جافاسكريبت وبايثون وجافا وقواعد بيانات SQL ومحررات النصوص وأدوات سطر الأوامر مثل grep وحتى دوال جداول البيانات. تعلمها مرة واحدة وستستخدمها في كل مكان طوال مسيرتك.
المستوى الأول: المحارف الحرفية
أبسط تعبير نمطي هو مجرد نص. النمط cat يطابق الحروف c ثم a ثم t متتالية في أي مكان من المدخل. يطابق "cat" و"catalog" و"scatter" لأن الثلاثة تحتوي هذا التتابع.
هذا يكشف مبكرا أهم عادة في التعبيرات النمطية: فكر فيما يطابقه نمطك مما لم تقصده. يكتب المبتدئون cat قاصدين كلمة قطة، فتفاجئهم "scatter". معظم أخطاء التعبيرات النمطية أنماط فضفاضة أكثر من اللازم، لا مفرطة الصرامة.
المستوى الثاني: فئات المحارف
الأقواس المربعة تعني "أي محرف واحد من هذه المجموعة":
[aeiou]يطابق حرف علة واحدا[0-9]يطابق رقما واحدا؛ الشرطة تدل على مدى[a-zA-Z]يطابق حرفا لاتينيا واحدا بأي حالة[^0-9]يطابق محرفا واحدا ليس رقما؛ إشارة القبعة داخل الأقواس تعني النفي
المجموعات الشائعة لها اختصارات:
\dرقم، مثل[0-9]\wمحرف كلمة: حرف أو رقم أو شرطة سفلية\sمسافة بيضاء: مسافة أو جدولة أو سطر جديد- الأحرف الكبيرة تنفي:
\Dليس رقما، و\Wليس محرف كلمة، و\Sليست مسافة
النقطة . تطابق أي محرف واحد عدا السطر الجديد. هذا يجعلها مريحة بشكل خطير. a.c يطابق "abc" و"a7c" و"a c". إن قصدت النقطة نفسها فهرّبها: \..
جرب الآن: في المختبر، شغل \d\d\d على "call me at 555-0192". سيميز 555 و019. المطابقة الثانية تفاجئ معظم الناس، وفهم سببها (التعبير يطابق حيثما استطاع، دون أي فكرة عن نيتك) هو اللحظة التي تبدأ فيها التعبيرات النمطية بالمعقولية.
المستوى الثالث: المكررات
المكررات تحدد عدد مرات تكرار العنصر السابق:
*تعني صفرا أو أكثر+تعني واحدا أو أكثر?تعني صفرا أو واحدا، أي اختياري{3}تعني ثلاثا بالضبط، و{2,5}بين اثنتين وخمس، و{2,}اثنتين على الأقل
إذن \d{3}-\d{4} يطابق "555-0192". وcolou?r يطابق "color" و"colour" معا.
الجشع مقابل الكسل: الفخ الكلاسيكي
المكررات جشعة: تلتهم أكبر قدر ممكن ما دامت المطابقة ممكنة. في النص <b>bold</b> and <i>italic</i>، النمط <.*> لا يطابق <b>. بل يطابق السلسلة كلها من أول < إلى آخر >، لأن .* ابتلعت كل ما بينهما.
إضافة ? بعد المكرر تجعله كسولا يطابق أقل قدر ممكن: <.*?> يطابق <b> ثم </b> ثم <i> ثم </i> كلا على حدة. عندما يلتهم نمط نصا أكثر بكثير مما قصدت، فالجشع هو السبب دائما تقريبا.
المستوى الرابع: المراسي والحدود
المراسي تطابق مواضع لا محارف:
^يطابق بداية السلسلة$يطابق نهايتها\bيطابق حد كلمة، الموضع بين محرف كلمة ومحرف غير كلمة
المراسي تحول "يحتوي" إلى "يساوي". النمط \d+ يجد أرقاما في أي مكان من "abc123"، لكن ^\d+$ يشترط أن تكون السلسلة كلها أرقاما، وهذا ما تريده فعلا عند التحقق من حقل كمية.
والحدود تحل مشكلة "cat داخل scatter" من المستوى الأول: \bcat\b يطابق "cat" ككلمة، لا "cat" داخل "scatter" أو "catalog".
في أعمال التحقق، أرس كل شيء. فحص بريد إلكتروني بلا ^ و$ سيقبل بسرور garbage my@email.com garbage.
المستوى الخامس: المجموعات والتخيير
الأقواس تجمع، والخط العمودي يعني "أو":
(cat|dog)يطابق أيا من الكلمتين(ab)+يطابق "ab" و"abab" و"ababab"؛ المكرر ينطبق على المجموعة كلها^(GET|POST|PUT|DELETE)يطابق أسطر طرق HTTP في سجل
المجموعات تلتقط أيضا ما طابقته، وهذا يشغل الاستبدال. لنقل إن لديك تواريخ مثل 07/08/2026 وتحتاج 2026-07-08. النمط: (\d{2})/(\d{2})/(\d{4}). كل جزء بين قوسين يُخزن: المجموعة 1 هي 07، والمجموعة 2 هي 08، والمجموعة 3 هي 2026. نص الاستبدال $3-$1-$2 (أو \3-\1-\2 في بعض الأدوات) يعيد تركيبها بالترتيب الجديد. هذه التقنية الواحدة، البحث بمجموعات وإعادة الترتيب في الاستبدال، ستوفر عليك ساعات من التحرير اليدوي على مدى مسيرتك. تدعم أداة البحث والاستبدال لدينا الاستبدال بالتعبيرات النمطية إن أردت التمرن على نص حقيقي.
إن احتجت تجميعا بلا التقاط، فالصيغة (?:...) تجمع بصمت. تبقي أرقام المجموعات مرتبة في الأنماط المعقدة.
المجموعات المسماة تجعل الأنماط موثقة ذاتيا: (?<year>\d{4}) تلتقط باسم "year"، ويشار إليها بـ $<year> في استبدالات جافاسكريبت.
المستوى السادس: تهريب المحارف الخاصة
لهذه المحارف معان خاصة ويجب تهريبها بشرطة مائلة عكسية لمطابقتها حرفيا: . * + ? ^ $ ( ) [ ] { } | \ /.
لمطابقة السعر "$5.99" تكتب \$5\.99. نسيان تهريب النقطة هو أشيع خطأ في التعبيرات النمطية على الإطلاق، لأن النقطة غير المهربة تعمل رغم ذلك؛ لكنها تطابق أيضا ما لا ينبغي. النمط buildquill.com يطابق بكل سرور "buildquillXcom".
التطبيق: بناء نمط خطوة بخطوة
الأنماط الحقيقية تبنى تدريجيا مع اختبار كل خطوة. لنفترض أننا نريد مطابقة أسعار مثل "$1,299.99" في نص.
- ابدأ بعلامة الدولار مهربة:
\$ - أضف أول مجموعة أرقام، من 1 إلى 3:
\$\d{1,3} - اسمح بمجموعات آلاف مفصولة بفواصل ومكررة:
\$\d{1,3}(?:,\d{3})* - اسمح بجزء عشري اختياري:
\$\d{1,3}(?:,\d{3})*(?:\.\d{2})?
اختبر كل مرحلة على أمثلة موجبة ("$5" و"$1,299.99") وسالبة ("$12345.9" و"$,300"). البناء خطوة خطوة مع الاختبار المستمر هو طريقة المحترفين في كتابة التعبيرات النمطية. لا أحد يكتب النمط النهائي دفعة واحدة.
أنماط ستستخدمها فعلا
إليك عدة بداية من أنماط عملية لتدرسها لا لتنسخها فقط. كل منها يستخدم المفاهيم أعلاه حصرا.
إزالة المسافات من نهايات الأسطر (للتنظيف بالاستبدال):
\s+$ مستبدلا بلا شيء، في وضع الأسطر المتعددة.
دمج المسافات المتعددة في واحدة:
{2,} مستبدلا بمسافة واحدة.
استخراج كل الوسوم:
#\w+
مطابقة وقت مثل 09:30 أو 23:59:
^([01]\d|2[0-3]):[0-5]\d$
مطابقة عنوان IPv4 تقريبي (نسخة عملية):
^\d{1,3}(\.\d{1,3}){3}$
لاحظ أنه يقبل "999.999.999.999". لمعظم أعمال تحليل السجلات هذا مقبول. النسخة الصارمة موجودة لكنها أطول بكثير، ومعرفة متى يكون التساهل مقبولا جزء من المهارة.
فحص بريد إلكتروني عملي:
^[^\s@]+@[^\s@]+\.[^\s@]+$
يقول: محارف ليست مسافة ولا @، ثم @، ثم المزيد، ثم نقطة، ثم المزيد. يرفض الهراء الواضح ويقبل كل العناوين الحقيقية. لا تطارد النمط "المثالي" للبريد الإلكتروني؛ حتى نمط المعيار الرسمي وحش شهير، والتحقق الحقيقي الوحيد هو إرسال رسالة تأكيد.
الرايات
يدعم كل محرك تعبيرات نمطية رايات معدلة. الثلاث المهمة يوميا:
- i (تجاهل الحالة): النمط
catمع راية i يطابق "Cat" و"CAT" - g (شامل): إيجاد كل المطابقات بدل التوقف عند الأولى
- m (أسطر متعددة): تجعل
^و$يطابقان بداية ونهاية كل سطر بدل السلسلة كلها، وهذا أساسي عند معالجة نصوص سطرية كالسجلات وملفات CSV
كيف تتمرن لتثبت المهارة؟
تتبخر معرفة التعبيرات النمطية بلا استخدام. ثلاثة تمارين تبني مهارة دائمة:
- اسرد الأنماط التي تقابلها. عندما تصادف تعبيرا نمطيا في كود، ترجمه إلى لغة عادية بصوت عال، من اليسار إلى اليمين: "بداية السلسلة، رقم واحد أو أكثر، شرطة..." إن عجزت عن سرده فاختبره على مدخلات عينة حتى تستطيع.
- حل مشكلات نصوصك به. في المرة القادمة التي تحتاج فيها لتنظيف قائمة أو إعادة تنسيق تواريخ أو استخراج قيم من سجل، قاوم إغراء العمل اليدوي. ستستغرق المهمة وقتا أطول في المرات الخمس الأولى، ثم لن يتكرر ذلك أبدا.
- اقرأ الإخفاقات بتمعن. عندما يسيء نمط التصرف، لا تعدل عشوائيا. اعثر على المدخل المحدد الذي يخالف فيه السلوك توقعك، ثم استنتج أي جزء مسؤول. هكذا بالضبط تتعلم دروس الجشع والإرساء بالحدس.
ملاحظة عن التراجع الكارثي: الأنماط ذات المكررات المتداخلة مثل (a+)+ على مدخل غير مطابق قد تستغرق وقتا أسيا وتجمد التطبيقات. إن علق نمط على مدخلات معينة، فابحث عن تكرار متداخل وأعد الكتابة بحيث لا تتضاعف الاحتمالات.
إلى أين بعد ذلك؟
تعرف الآن فئات المحارف والمكررات والمراسي والمجموعات والتخيير والتهريب والرايات. هذا يغطي أكثر من 90 بالمئة من الاستخدام الواقعي. المواضيع المتبقية، النظر الأمامي (?=...) والنظر الخلفي (?<=...) والإشارات الراجعة \1 وفئات يونيكود \p{...}، تستحق التعلم بعد أن تصبح الأساسيات تلقائية، وكل منها يحل مشكلة محددة ستتعرف عليها حين تصطدم بها.
أبق مختبر التعبيرات النمطية في مفضلتك، وابن الأنماط تدريجيا، واسرد ما تقرأ. خلال أسابيع قليلة من الاستخدام العرضي، سيُقرأ السطر غير المفهوم في أول هذا المقال في ذهنك كجملة عادية.