مطابقة عدة مجموعات نمطية في التعابير النمطية RegEx
تُعدُّ التعابير النمطية (Regular Expressions أو RegEx) أداة قوية ومرنة للغاية تُستخدم في معالجة النصوص والبيانات بشكل عام. من خلال هذه الأداة، يمكن للمبرمجين والمطورين البحث، التحقق، والتلاعب بالنصوص اعتماداً على أنماط معينة يحددونها مسبقاً. في العديد من الحالات العملية، قد يكون من الضروري مطابقة عدة مجموعات نمطية في نص واحد، وهذا يتطلب فهمًا عميقًا لكيفية عمل التعابير النمطية، وكيفية بناء أنماط متقدمة تتضمن مجموعات متعددة. هذا المقال يقدم شرحًا مفصلاً وموسعًا حول مفهوم مطابقة عدة مجموعات نمطية في RegEx، آلياتها، تقنياتها، واستخداماتها المختلفة في مجالات البرمجة ومعالجة النصوص.
مفهوم المجموعات النمطية في التعابير النمطية
قبل التعمق في مطابقة عدة مجموعات، يجب فهم ما تعنيه “المجموعة النمطية” في سياق التعابير النمطية. المجموعة النمطية (Group) هي جزء من التعبير النمطي يتم تحديده باستخدام الأقواس المستديرة ( ). هذه المجموعات تتيح التقاط جزء معين من النص الذي يتطابق مع هذا الجزء من النمط، وحفظه لاستعماله لاحقًا، سواء في عمليات استبدال، أو استرجاع القيم، أو للتحقق من وجود أكثر من جزء معين في النص.
على سبيل المثال، في التعبير النمطي التالي:
scss(\d{3})-(\d{4})
-
المجموعة الأولى
( \d{3} )تلتقط ثلاثة أرقام. -
المجموعة الثانية
( \d{4} )تلتقط أربعة أرقام. -
النص الذي يتطابق مع هذا النمط هو نص يحتوي على ثلاثة أرقام، متبوعة بشرطة، ثم أربعة أرقام، مثل رقم هاتف.
يمكن الوصول إلى كل مجموعة على حدة واستخدامها كما يشاء المبرمج.
لماذا نحتاج إلى مطابقة عدة مجموعات نمطية في نفس النص؟
في العديد من سيناريوهات البرمجة والتطبيقات العملية، يكون النص الذي يتم التعامل معه معقدًا ويحتوي على عدة أجزاء مهمة، كل منها يجب التعرف عليه بشكل مستقل. هذا يجعل من الضروري استخدام عدة مجموعات نمطية في نفس التعبير.
على سبيل المثال:
-
استخراج أسماء المستخدمين وعناوين البريد الإلكتروني في نفس الوقت من نص طويل.
-
التحقق من صحة تنسيق معقد مثل أرقام الهواتف، الرموز البريدية، والتواريخ في نص واحد.
-
تحليل سجلات الخادم (logs) التي تحتوي على عدة أجزاء منظمة بتنسيق معين.
باستخدام المجموعات النمطية، يمكن التقاط كل جزء بشكل منفصل دون الحاجة إلى معالجة النصوص يدوياً أو استخدام دوال متعددة.
بناء التعبير النمطي لمطابقة عدة مجموعات
1. المجموعات العادية (Capturing Groups)
كما ذكرنا، استخدام الأقواس المستديرة () لإنشاء مجموعات نمطية يقوم بالتقاط النص المتطابق مع النمط داخلها. كل مجموعة يتم ترقيمها تلقائيًا حسب ترتيب ظهورها في التعبير، ابتداءً من 1.
مثال:
regex([A-Za-z]+) (\d+)
هذا التعبير يبحث عن كلمة تتكون من أحرف تليها مسافة ثم رقم واحد أو أكثر. سيتم التقاط الكلمة في المجموعة الأولى، والرقم في المجموعة الثانية.
2. المجموعات غير الملتقطة (Non-Capturing Groups)
في بعض الحالات، قد نحتاج إلى تجميع أجزاء من النمط بدون الحاجة إلى حفظها كجزء منفصل يمكن الرجوع إليه. تُستخدم الأقواس مع علامة استفهام ونجمة (?:...) لتحقيق ذلك.
مثال:
regex(?:cat|dog) food
يبحث عن “cat food” أو “dog food”، لكنه لا يحفظ كلمة “cat” أو “dog” كمجموعة.
3. المجموعات المتداخلة (Nested Groups)
يمكن استخدام مجموعات داخل مجموعات أخرى، مما يتيح بناء تعابير نمطية معقدة للغاية.
مثال:
regex((\d{3})-(\d{2}))-(\d{4})
-
المجموعة الأولى:
((\d{3})-(\d{2})) -
المجموعة الثانية:
(\d{3}) -
المجموعة الثالثة:
(\d{2}) -
المجموعة الرابعة:
(\d{4})
هذا النمط يمكن أن يستخدم لتحليل أرقام الضمان الاجتماعي في بعض الدول.
التقاط عدة مجموعات متعددة في النص
عندما نتحدث عن مطابقة عدة مجموعات نمطية، يمكن أن نعني إما:
-
وجود عدة مجموعات في نفس التعبير النمطي، بحيث تتطابق مع أجزاء مختلفة من النص.
-
العثور على جميع التطابقات لمجموعة نمطية واحدة أو أكثر في نص يحتوي على تكرار لهذه الأنماط.
1. التطابق مع مجموعات متعددة في نص واحد
يمكن أن يحتوي التعبير النمطي الواحد على عدة مجموعات، كل منها يلائم جزءًا معينًا من النص. على سبيل المثال:
regex(\w+)@(\w+)\.(\w+)
في هذا التعبير، يتم التقاط:
-
اسم المستخدم قبل علامة @ في المجموعة الأولى.
-
اسم النطاق (domain) في المجموعة الثانية.
-
لاحقة النطاق (مثل com أو org) في المجموعة الثالثة.
2. العثور على تكرارات للمجموعات النمطية
عند التعامل مع نص طويل يحتوي على عدة أجزاء متشابهة، يمكن استخدام g (global) أو ما يقابلها في لغات البرمجة المختلفة للبحث عن كل التكرارات.
مثال باستخدام جافاسكريبت:
javascriptconst regex = /(\d{3})-(\d{4})/g;
const text = "123-4567 and 234-5678 are phone numbers.";
let match;
while ((match = regex.exec(text)) !== null) {
console.log(`Found number: ${match[0]}, Area: ${match[1]}, Number: ${match[2]}`);
}
في هذا المثال يتم استخراج كل أرقام الهواتف وتفصيلها إلى مجموعاتها.
استخدام المجموعات النمطية مع العمليات الشرطية
تدعم بعض محركات RegEx إمكانيات متقدمة مثل:
-
المجموعات الشرطية (Conditional Groups)
-
عمليات التكرار المتقدمة (Quantifiers)
-
المجموعات المتقدمة مثل Lookahead و Lookbehind
1. المجموعات الشرطية (Conditional Groups)
تسمح بتنفيذ تطابق يعتمد على تحقق شرط معين في المجموعة النمطية.
مثال:
regex(\d{3})(?(1)-\d{2})
هذا التعبير يقول: إذا كان هناك تطابق في المجموعة الأولى (3 أرقام)، يجب أن يتبعها شرطة ثم رقمين.
2. Lookahead و Lookbehind
-
Lookahead يسمح بالتحقق من وجود نمط معين بعد الموضع الحالي دون تضمينه في التطابق.
-
Lookbehind يسمح بالتحقق من نمط قبل الموضع الحالي.
مثال على Lookahead:
regexfoo(?=bar)
يتطابق مع “foo” فقط إذا كان يتبعها “bar”.
مطابقة عدة مجموعات نمطية مع تكرار داخل النص (تطبيقات عملية)
في الكثير من التطبيقات البرمجية، يمكن أن تتطلب الحاجة إلى مطابقة عدة مجموعات نمطية متكررة في نص طويل. هذا يحدث مثلاً عند التعامل مع ملفات السجلات (logs)، ملفات CSV، أو أي مستند نصي معقد.
مثال عملي: تحليل سجلات (Logs)
يحتوي سجل على معلومات عدة مفصولة بفواصل أو رموز خاصة، مثل:
yaml2025-05-18 12:00:01 ERROR UserID=12345 Action=Login Failed
2025-05-18 12:05:10 INFO UserID=54321 Action=Logout Success
يمكن استخدام التعبير النمطي التالي:
regex(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+) UserID=(\d+) Action=(\w+)
هذا التعبير يلتقط:
-
التاريخ
-
الوقت
-
نوع الرسالة (ERROR, INFO, …)
-
معرف المستخدم
-
الإجراء المنجز
يمكن بعد ذلك معالجة كل مجموعة بشكل مستقل في البرنامج.
التعامل مع المجموعات في لغات البرمجة المختلفة
مفهوم المجموعات النمطية موجود في كل لغات البرمجة التي تدعم RegEx، ولكن طريقة التعامل تختلف قليلاً.
| اللغة | طريقة الوصول إلى المجموعات | ملاحظات مهمة |
|---|---|---|
| Python | match.group(n) |
group(0) هو النص الكامل المطابق |
| JavaScript | match[n] أو من خلال exec() |
match[0] النص الكامل المطابق |
| Java | matcher.group(n) |
|
| PHP | $matches[n] بعد استخدام preg_match |
|
| Ruby | match[n] |
التحديات والحلول في مطابقة مجموعات نمطية متعددة
1. التعامل مع التعارضات بين المجموعات
عندما تكون هناك مجموعات متداخلة أو متقاربة، قد يحدث تعارض في كيفية التقاط النصوص. الحل يتمثل في:
-
ترتيب المجموعات بعناية.
-
استخدام المجموعات غير الملتقطة حيث لا نحتاج للحفظ.
-
الاعتماد على الأدوات المتقدمة مثل Lookahead و Lookbehind لتحديد الحدود.
2. الأداء مع نصوص ضخمة
التعابير النمطية التي تحتوي على مجموعات متعددة ومعقدة قد تسبب بطء في الأداء، خصوصًا مع نصوص كبيرة. نصائح لتحسين الأداء:
-
تبسيط الأنماط بقدر الإمكان.
-
تجنب المجموعات غير الضرورية.
-
اختبار التعبير النمطي على عينات صغيرة قبل تطبيقه على كامل النص.
استخدام المجموعات في استبدال النصوص
يمكن استخدام المجموعات النمطية في دوال الاستبدال لاستبدال أجزاء معينة من النص أو إعادة ترتيبها.
مثال في Python:
pythonimport re
text = "Doe, John"
pattern = r"(\w+), (\w+)"
replaced = re.sub(pattern, r"\2 \1", text)
print(replaced) # النتيجة: John Doe
في هذا المثال، المجموعتان تلتقطان الاسم واللقب، ثم يتم إعادة ترتيبهما في النص الجديد.
الفرق بين المجموعات العادية والمجموعات اللافتة للنظر (Lookaround Groups)
-
المجموعات العادية تقوم بالتقاط النص ومطابقته.
-
المجموعات اللافتة للنظر (Lookahead, Lookbehind) تقوم بالتحقق من وجود نمط معين دون تضمينه في النص المتطابق.
أمثلة شاملة على مطابقة عدة مجموعات نمطية
مثال 1: استخراج تفاصيل الاتصال
نص يحتوي على أسماء، أرقام هواتف، وعناوين بريد إلكتروني:
yamlName: Ali Ahmed, Phone: 0551234567, Email: [email protected]
Name: Sara Khalid, Phone: 0559876543, Email: [email protected]
تعبير نمطي لاستخراج كل المجموعات:
regexName: ([A-Za-z ]+), Phone: (\d{10}), Email: ([\w\.]+@[\w\.]+)
-
المجموعة 1: الاسم
-
المجموعة 2: رقم الهاتف
-
المجموعة 3: البريد الإلكتروني
مثال 2: تحليل تواريخ متعددة وتنسيقات مختلفة
يمكن إنشاء تعبير نمطي يحتوي على مجموعات متعددة ليطابق عدة تنسيقات للتاريخ:
regex(\d{4})-(\d{2})-(\d{2})|(\d{2})/(\d{2})/(\d{4})
هذا يسمح بالتعرف على التاريخ في شكلين:
-
السنة-الشهر-اليوم (YYYY-MM-DD)
-
اليوم/الشهر/السنة (DD/MM/YYYY)
الخلاصة
مطابقة عدة مجموعات نمطية في التعابير النمطية تُعتبر من المهارات الأساسية المتقدمة في التعامل مع النصوص والبيانات. استخدام المجموعات بشكل صحيح وفعال يساعد على تقسيم النصوص المعقدة إلى أجزاء منظمة يمكن التعامل معها برمجياً بطريقة دقيقة وفعالة. بالإضافة إلى ذلك، فهم الفرق بين المجموعات العادية، المجموعات غير الملتقطة، والمجموعات الشرطية، بالإضافة إلى أدوات مثل Lookahead و Lookbehind، يفتح آفاقاً واسعة لبناء تعابير نمطية قوية ومتعددة الوظائف.
كما أن التمكن من استرجاع المجموعات والتعامل معها في لغات البرمجة المختلفة، يشكل حجر الزاوية في بناء حلول برمجية متكاملة لتحليل البيانات، التحقق من صحة المعلومات، والتعديل التلقائي للنصوص. لذلك، يُعد استثمار الوقت لفهم هذه المفاهيم والتقنيات مهماً لأي مطور أو مبرمج يسعى لتحقيق نتائج دقيقة وذات جودة عالية في مجال معالجة النصوص.
المصادر والمراجع
-
Jeffrey E. F. Friedl, “Mastering Regular Expressions,” O’Reilly Media, 3rd Edition, 2006.

