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

مقدمة في التعابير النمطية Regular Expressions


طريف العتيق

نحتاج في أحيانٍ كثيرة إلى إدخال تعديلات محدّدة على بعض الملفات، فمديرو نظم التشغيل يحتاجون أحيانًا إلى تعديل مجموعة فقط من عناوين الـ IP التي تنتمي إلى فئة ما، أو مجموعة من أسماء النطاقات domains (أو النطاقات الفرعية)، بل ربما احتاج أحدنا إلى تصحيح بعض الأخطاء الكتابية المتكرّرة في ملفٍ طويل، كحذف الأسطر الفارغة مثلًا، أو المسافات الفارغة في بدايات الأسطر، تغطّي التعابير النمطيّة Regular Expressions التعامل مع هذا النوع من المشاكل.

التعابير النمطيّة هي أسلوب يُستخدم لوصف النصوص والتعرّف عليها من خلال مطابقتها (أو عدم مطابقتها) مع رموز محدّدة، وتنتشر تطبيقاتها في عدد متزايد من برامج معالجة النصوص، ومحرّرات اللغات البرمجيّة وغيرها. نتناول في هذا الدرس شرح أساسيات التعامل مع هذه التعابير دون تخصيص الحديث عن برنامج ما، حيث سنستخدم الأداة egrep في أمثلتنا (والتي تستخدم للبحث ضمن الملفات النصيّة أو دخل المستخدم عن طريق التعابير النمطيّة وطباعة الخرج المطابق لها على شاشة الطرفية).

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

تدعم التعابير النمطيّة نوعين من المحارف:

  • الأول هو الأحرف الأبجديّة المعروفة، 
  • والآخر هو الرموز الخاصة Metacharacters، وهي ما تعطي التعابير النمطية فاعليتها الحقيقية.

لنأخذ الملف التالي country.txt كمثال، وهو - كما نرى - مؤلف من سبعة أسطر وثلاثة أعمدة، العمود الأول يحمل اسم البلد، والثاني عدد سكانه، والأخير القارّة التي يقع فيها:

$ cat country.txt 
India,1014003817,Asia 
Italy,57634327,Europe 
Yemen,1184300,Asia 
Argentina,36955182,Latin America 
Brazil,172860370,Latin America 
Cameroon,15421937,Africa 
Japan,126549976,Asia

 

محارف الإرساء الخاصة

لنبدأ في شرح المحارف الخاصة مع العلامتين ^ و $، واللتان تشيران إلى أول السطر وآخره على التتالي، وتسمى بمحارف الإرساء anchor metacharacters. فلو رغبنا مثلًا بمعرفة الأسطر التي تبدأ بحرف "I"، فإننا سنستخدم التعبير:

$ egrep '^I' country.txt 
India,1014003817,Asia 
Italy,57634327,Europe

وبالمثل، لتحديد الأسطر التي تنتهي بحرف "e"، نكتب:

$ egrep 'e$' country.txt 
Italy,57634327,Europe

العلامة التالية هي النقطة (.)، والتي تشير إلى محرف واحد (حرف، رقم، أو علامة)، فللبحث عن أسماء المدن المؤّلفة من خمسة محارف نطبع الأمر:

$ egrep '^.....,' country.txt 
India,1014003817,Asia 
Italy,57634327,Europe 
Yemen,1184300,Asia 
Japan,126549976,Asia

الآن لنجرّب البحث عن الأسطر التي تبدأ بحرف "I" أو "J" ومؤلفة من خمسة محارف:

$ egrep '^[IJ]....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976

تسمّى الأقواس المستطيلة [] هنا بصفّ المحرف character class، وهي تبحث عن تطابق واحد فقط من المحارف التي تضمها مع النصّ. وإذا وضعنا بداخلها العلامة ^ فإنها تصبح صفّ استبعاد، أي تطابق كل النصّ المذكور عدا ما يلحقها، فلو أردنا البحث عن أسماء البلدان المؤلفة من خمسة محارف والتي لا يبدأ اسمها بحرف "J" ولا "I" فإننا نكتب:

$ egrep '^[^IJ]....,' country.txt 
Yemen,1184300,Asia

 

مجموعات المحارف الخاصة وتنويعاتها

لمطابقة جميع الأسطر التي تضم كلمة Asia أو Africa نكتب:

$ egrep 'Asia|Africa' country.txt 
India,1014003817,Asia 
Yemen,1184300,Asia 
Cameroon,15421937,Africa 
Japan,126549976,Asia

كما يمكن إجراء ذات البحث باستخدام تعبير نمطي يستخرج حرفي A و a كعوامل مشتركة في الكلمتين:

$ egrep 'A(si|fric)a' country.txt 
India,1014003817,Asia 
Yemen,1184300,Asia 
Cameroon,15421937,Africa 
Japan,126549976,Asia

تحديد الكميّة

بدلًا من كتابة العبارة:

$ egrep '^[IJ]....,' country.txt

 يمكننا اختصارها بالشكل:

$ egrep '^[IJ].{4},' country.txt 

يسمى القوسين المزهّرين هنا {} بمحدّدي الكمية، وتضم رقم يعبّر عن عدد المرات التي يجب أن يتكرر فيها المحرف قبل مطابقته، كما تُستخدم للتعبير عن مدى (مجال) من المرات:

$ egrep '^[IJ].{4,6},' country.txt 
India,1014003817,Asia 
Italy,57634327,Europe 
Japan,126549976,Asia

يبحث التعبير النمطي السابق عن أسماء البلدان التي تبدأ بالحرف "I" أو "J" وتتراوح عدد محارفها من 4 إلى 6. هناك أيضًا بعض الاختصارات التي يمكن استخدامها مع تحديد الكمية مثلًا المجال {0,1} والذي يعني "يوجد مرة واحدة على الأقل أو لا يوجد تمامًا"، يُكافئ بالرمز ؟، حيث يمكننا كتابة:

$ egrep '^ab{0,1}c$' filename

أو:

$ egrep '^ab?c$' filename 

أيضًا المجال {0,} يُكافئ بالرمز *، والتي تعني عدد لا نهائي من المرات، حيث التعبير:

$ egrep '^ab{0,}c$' filename

يساوي بالنتيجة:

$ egrep '^ab*c$' filename 

وكذلك المجال {1,} والذي يحدّد الكمية "مرّة واحدة على الأقل"، يُكافئ بالرمز +، ويكون التعبيرين التاليين متكافئين:

$ egrep '^ab{1,}c$' filename 

$ egrep '^ab+c$' filename

لنأخذ الآن بعض الأمثلة الأكثر تعقيدًا ولندمج ما تعلمناه من تعابير، لكن عوضًا عن البحث ضمن ملف نصيّ txt سنعالج دخل قياسي من قبل المستخدم. لنبحث مثلًا عن كل الاحتمالات الممكنة في تهجئة الجملة التالية: the grey colour suit was his favourite

$ egrep 'the gr[ea]y colou?r suit was his favou?rite' 
the grey color suit was his favourite 
the grey color suit was his favourite 

the gray colour suit was his favorite 
the gray colour suit was his favorite

لو نظرنا إلى التعبير المستخدم في هذا المثال، فإننا سنرى:

  • الكلمة "grey" يمكن أن تلفظ grey أو gray.
  • الكلمة "colour" تكتب بطريقتين: colour أو color،

وهذا يعني بأن حرف (u) اختياري، لذلك استخدمنا العلامة ؟ والتي تعني "يوجد مرة واحدة على الأقل أو لا يوجد تمامًا. + كذلك الأمر مع الكلمة "favourite" حيث كتابة حرف (u) اختيارية لذا استخدمنا ذات العلامة ؟

لنجرّب الآن مطابقة عنوان الرمز البريدي zip code في الولايات المتحدة:

$ egrep '^[0-9]{5}(-[0-9]{4})?$' 
83456 
83456 
83456- 
834562 
92456-1234 
92456-1234 
10344-2342-345
مثال آخر يطابق جميع الأوقات الممكنة في الأربع والعشرين ساعة:
$ egrep '^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]' 
23:44:02 
23:44:02 
33:45:11 
15:45:33 
15:45:33

في المثال السابق قلنا أنه إذا كانت الخانة الأولى من الساعة إما 0 أو 1، عندها يسمح للخانة الثانية بأن تأخذ قيمة من المجال من 0 إلى 9، ولكن إذا كانت الخانة الأولى تحمل الرقم 2 حينها يسمح للخانة الثانية أن تأخذ القيم 0، 1، 2، أو 3.

حدود الكلمة

لكتابة تعبير نمطي يطابق الكلمات التي تنتهي بـ "color"، سنرى أنه يطابق الأمثلة: unicolor ،watercolor ،multicolor، لكنه لن يطابق colorless أو colorful: 

تطابق العلامة "<\" ورود كلمة color آخر الكلمة مثل unicolor، watercolor، أو multicolor،

$ egrep 'color\>'

أما لمطابقة كلمة color في أوّل الكلمة، مثل colorless أو colorful، فإننا نكتب:

$ egrep '\<color'

ولمطابقة كلمة color كما هي:

$ egrep '\<color\>'

الإحالات المرجعية

لنفترض أننا نريد مطابقة جميع الكلمات المكرّرة مثل "the the" أو "before before"، هنا نستخدم ما يسمى بالإحالات المرجعية backreferences والتي تستعمل لتذكّر الأنماط، مثال:

$ egrep "\<the\> \1" 

أو في الحالة العامّة:

$ egrep "\<(.*)\> \1" 

يطابق التعبير السابق جميع الكلمات عندما تتشابه الثانية مع الأولى، كما يمكن استخدام زوج إضافي من الأقواس مع المرجع 2\ لمطابقة الكلمات فقط إذ تكررت أربع مرات، وهكذا..

ترجمة -وبتصرّف- للمقال: An Introduction To Regular Expressions للكاتب: Shantanu Kulkarni.


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

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

لا توجد أية تعليقات بعد



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...