docs:regex-basics

بدهيات الأنماط القياسية REGEX

الأنماط القياسية Regular Expression أو REGEX اختصارا هي وسيلة شائعة جدا في معالجة النصوص string manipulation في

  • عمليات المطابقة Matching (مثلا فحص هل أدخل المستخدم بريد إلكتروني صحيح)
  • والبحث (مثلا استخراج كل الروابط من ملف HTML)
  • الاستبدال (وضع كل الروابط بين وسم <a>)

إن أكثر تطبيقاتها هي عمل parsers لكنها لا تقف عند هذا الحد. عمليات البحث والمطابقة للأنماط القياسية سريعة نسبيا حيث أنه أولا يتم تصنيف النمط compile وهي عملية تحوله من NFA أي nondeterministic finite automaton إلى DFA أي deterministic finite automaton في عملية تسمى Powerset construction ثم يتم تمرير حروف النص فيها.

أنواع الأنماط

  • أنماط مستهلكة consuming وهي التي تطابق حرف أو أكثر وتستهلكها
    • الأنماط الحرفية وهي التي نقصدها كما هي دون معنى خاص
    • الانتماء لمجموعة set أو عدم الانتماء لها
    • التجميع grouping وهو وضع عدة أنماط بين قوسين لبيان الأولية وهي نوعان capturing و non-capturing الأول يتم حفظه ويمكن الرجوع له back reference أما الثاني فلا.
    • المحددات العددية للنمط السابق Quantification (مثل عدد مرات التكرار)
      • أنماط جشعة greedy patterns وهي التي تبحث عن أطول تطابق وهذا هو السلوك التلقائي
      • أنماط غير جشعة non-greedy patterns وهي التي تبحث عن أقصر تطابق
  • أنماط غير مستهلكة non-consuming (وكأنها تطابق المؤشر الموجود بين الحروف وليس عدد من الحروف) مثل
    • الموضعية (كبادية السطر أو نهايته أو بداية الكلمة)
    • الشروط على ما سبق أو ما سيأتي دون استهلاكها

المطابقة الحرفية

الأنماط الحرفية هي التي نقصد المعنى الحرفي لها مثلا عندما نقول car فإننا نعني حرف c يتبعه حرف a يتبعه حرف r. علامة النقطة “.” تطابق أي حرف واحد مثلا p.t تطابق حرف p يليه أي حرف (بما في ذلك الرموز والمسافات) يليه t مثل pot و pet.

ويمكننا التخيير باستعمال علامة | مثلا apple|banana تطابق كلمة apple أو كلمة banana. ويجوز وضع علامة | أكثر من مرة

<note> هناك أكثر من تنفيذ للأنماط القياسية وأكثر من مكتبة. الأنماط القياسية العيارية الأسياسية يرمز لها بالرمز BRE والممتدة ب ERE وهما المستخدمان في أمر grep الشهير. وأشهره منهما الخاصة بلغة بيرل perl regex والتي تستعريها منها أغلب اللغات الأخرى. </note>

إن كان هناك معنى خاص لأي حرف وكنا نريده بشكل حرفي يمكنني تخطي المعنى الخاص بعلامة الشرطة المائلة العكسية \

<note> في BRE يكون التخطي أحيانا بعدم وضع علامة / والمعنى الخاص هو بعلامة / </note>

الانتماء لمجموعة set

يتم اشتراط الحرف لمجموعة من الحروف عبر وضع كل الحروف الممكنة بين أقواس مربعة [ ] مثلا p[aei]n تطابق p يتبعه حرف من بين الحروف a أو e أو i ثم حرف n أي pan أو pen أو pin.

إن كانت الحروف متتابعة يمكن استخدام علامة - مثلا [a-z] تعني كل الحروف من a-z ومثلا [a-zA-Z] تعني كل الحروف a-z كبيرة وصغيرة.

لنفي الانتماء لمجموعة يمكن وضع علامة ^ بعد فتح القوس المربع مثلا a[^ ]b والتي تعني حرف a يتبعه أي شيء عدا المسافة ثم حرف b

التجميع grouping

يكون التجميع بوضع الأقواس حول النمط مثلا (apple|banana)

<note> في BRE الأقواس الحرفية هي الأقواس دون تخطي بعلامة / أما أقواس التجميع فهي مسبوقة بعلامة التخطي /. كذلك علامة | فإن كنت تعني بها أو عليك وضع علامة / قبلها. </note>

echo "banana eating monkey" | grep '\(apple\|banana\)' && echo matches
echo "banana eating monkey" | egrep '(apple|banana)' && echo matches

يقوم البرنامج بحفظ كل قوس ويمكنك من العودة إليه لاحظة عبر back reference كما سنوضح ذلك لاحقا.

المحددات العددية

  • علامة النجمة * تكرار النمط صفر أو أكثر من المرات
  • علامة الزائد + تكرار النمط واحد أو أكثر من المرات (اشتراط وجوده مرة على الأقل)
  • علامة السؤال ? تكرار النمط مرة على الأكثر (أي أن النمط اختياري)
  • تحديد التكرار بين رقمين {n,m} أي على الأقل n مرة ولا يزيد عن m مرة

<note> في BRE علامات ? و + و { } بحاجة لتخطي كي تعطي المعنى الخاص </note>

إذا كان هناك أكثر من خيار فإن المطابقة ستكون لأطول خيار وهذا ما يعرف بالنمط الجشع greedy. وضع علامة السؤال بعد النجمة يعني يعني تحويلها إلى نمط غير جشع مثلا a[a-z]*?b تعني أقصر تطابق لكلمة تبدأ ب a وتنتهي ب b مثلا الجزء المطابق في abbbbbbbb هو أول حرفين فقط. المطابقة غير الجشعة غير قياسية (غير موجود في grep) بل هي موجودة في مكتبة perl (وكل اللغات التي تستخدم مكتبتها) والتي تقلدها.

<note important> المطابقة غير الجشعة مكلفة جدا فهي تحتاج وقت أطول وذاكرة أكثر. يفضل استخدام وسائل بديلة مثل استثناء الحروف. </note>

ومن أشهر الأمثلة التي نحتاج هذه الميزة فيها مطابقة النص داخل وسم <b></b> لاحظ المشكلة (وهي أن is a مظللة بالأحمر) ولاحظ الحل القياسي لها.

المحددات الموضعية

المحددات الموضعية كما ذكرنا سابقا لا تستهلك من المدخلات شيئا بل فقط تحدد المكان.

  • علامة ^ وتعني بداية النص أو السطر (إن كانت المطابقة متعددة الأسطر)
  • علامة $ وتعني نهاية النص أو السطر
  • حدود الكلمة \b وتعني على الحد الفاصل بين الكلمات (يعني إن كان قبلها محرف يجب أن لا يكون حرفا ولا رقما ولا _)

مثلا لعرض كل الأسطر التي تبدأ بكلمة Error اكتب

grep '^Error' /path/to/file

مثلا للبحث عن كلمة test كاملة وليس testing علينا اشتراط أن تقع على حد الكلمة من الطرفين كما في آخر مثال في الصورة

نقاش

بغداد دوكارة زكرياء, 2011/11/20 21:58

جزاك الله خيراً أستاذ مؤيد شرح رائع

Natalija, 2012/06/04 03:15

That's really thikning out of the box. Thanks!

Denisa, 2012/06/26 16:12

This is what we need - an insghit to make everyone think

vjhbbmhmw, 2015/04/24 16:27

بدهيات الأنماط القياسية REGEX [أعجوبة] vjhbbmhmw http://www.g87ql9tq61jhrt15af036nj0i79d04k0s.org/ [url=http://www.g87ql9tq61jhrt15af036nj0i79d04k0s.org/]uvjhbbmhmw[/url] <a href=“http://www.g87ql9tq61jhrt15af036nj0i79d04k0s.org/”>avjhbbmhmw</a>

أدخل تعليقك:
 
آخر تعديل:: 23 نيسان 2015 الساعة 00:20 (تحرير خارجي)