مدونة عمار الخوالده

متى لا تكون تعابير Regex كافية لتحليل النصوص؟

قُصاصة

كتبت سابقا مقالا تفاعليا يشرح Regex: مقدمة في تعلم Regex

شرحت فيه عدة أمثلة للمُطابقة (Matching) لكن ما لم يُذكر في المقال أن Regex يفشل أحيانا في معالجة بعض النصوص.

هذه القصاصة تعطي أمثلة على حالات لا يصلح فيها Regex لتحليل النصوص.

التكرار والتداخل Recursion

هذا النمط من المقال يُطابق بعض الـ HTML Tags:

<(strong|b)>(?<tag_content>.*)<\/(strong|b)>

لكن بالنظر إلى الى النص الآتي:

1<strong>Test <b>Bold</b> text</strong>

سيتم مطابقة <strong> و </strong> لكن Test <b>Bold</b> text ستُطابق كمجموعة واحدة تحت اسم tag_content. عند معالجة نمط معين، حيث يمكن لهذا النمط أن يحتوي على نفسه مرة أخرى (كوجود HTML tag داخل HTML tag آخر) فإن Regex يفشل في مطابقتها.

حتى إن قمت بمحاولة التكرار على هذا الشكل:

<(strong|b)>(.*<(strong|b)>(?<tag_content>.*)<\/(strong|b)>.*)*<\/(strong|b)>

فالفكرة لن تنجح.. ستتم المطابقة لكن غالبا لن تكون صحيحة، وستفشل بمجرد ادخال مزيد من المستويات أو أكثر من HTML Tag على نفس المستوى.

القواعد والعلاقات بين أجزاء النص

في نفس المثال السابق.. توجد مشكلة أخرى، ألا وهي العلاقة بين الأجزاء المختلفة للنص. فالنص التالي مثلا سيُطابق بشكل صحيح مع أنه HTML خاطئ:

1<b>test</strong>

يوجد حل لهذه المشكلة ألا وهو استخدام Backreference:

<(strong|b)>(?<tag_content>.*)<\/\1>

لكن المشكلة في عموما لا زالت قائمة، فليست كل القواعد يمكن حلها باستخدام هذه الطريقة، فمثلا عند تداخل اكثر من tag من نفس النوع، يفشل Regex في فهم النص.

مثال:

1<strong>Strong<strong>Stronger</strong><strong>

على فرض حل مشكلة التداخل في مثل هذا النص، فلا يمكن لـ Regex فهم التركيبة، ومثلها مشاكل الأقواس.

خلاصة

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

في هذه الحالات، يتم عمل Parsing للنص، وقد يُستخدم Regex لمعالجة الأجزاء الصغيرة (Tokens) كجزء من عملية الـ Parsing.

بعض محركات Regex قد تدعم مزايا اضافية تحل بعضا من المزايا، لكن الـ Parsing دائما هو الحل الأفضل متى ما كان النص معقدا أو يحوي كثيرا من الحالات.