التعبيرات النمطية في لغة C++ مع أمثلة: من الناحية العملية
\n\nالتعبيرات النمطية (regex) هي أداة قوية لمعالجة النصوص، تتيح البحث والاستبدال والتحقق من السلاسل النصية وفق أنماط معقدة. في لغة C++، ظهر دعم التعبيرات النمطية في المعيار C++11 من خلال المكتبة <regex>. في هذه المقالة، سنشرح كيفية استخدام std::regex عمليًا: من الفحوصات البسيطة إلى استخراج البيانات واستبدال النص.
ستكون المادة مفيدة لكل من المبتدئين الذين يتعرفون على لغة C++ لأول مرة، والمطورين ذوي الخبرة الذين يرغبون في تحديث معرفتهم. سنستعرض الوظائف الرئيسية: std::regex_match و std::regex_search و std::regex_replace، بالإضافة إلى العمل مع مجموعات الالتقاط.
المكونات الأساسية للمكتبة <regex>
\n\nقبل الانتقال إلى الأمثلة، دعنا نفهم الفئات والوظائف الأساسية:
\n\n- \n
- std::regex — فئة تمثل التعبير النمطي نفسه (النمط). يتم إنشاؤها من سلسلة نصية تحتوي على النمط وعلامة اختيارية لقواعد اللغة (افتراضيًا ECMAScript). \n
- std::smatch — حاوية لتخزين نتائج البحث (للسلاسل النصية من نوع
std::string). النظير هوstd::cmatchللسلاسل النصية من نوع C. \n - std::regex_match — تتحقق مما إذا كانت السلسلة النصية بأكملها تطابق النمط بالكامل. \n
- std::regex_search — تبحث عن سلسلة فرعية تطابق النمط في أي مكان داخل السلسلة النصية. \n
- std::regex_replace — تستبدل جميع التطابقات مع النمط بسلسلة نصية محددة (مع دعم المراجع العكسية). \n
جميع الوظائف تقبل علامات للتحكم في السلوك (على سبيل المثال، std::regex_constants::icase للبحث غير الحساس لحالة الأحرف).
مثال 1: التحقق من تطابق سلسلة نصية مع نمط (std::regex_match)
\n\nأبسط مهمة هي التحقق مما إذا كانت السلسلة النصية تطابق تنسيقًا معينًا. على سبيل المثال، دعنا نتحقق مما إذا كانت السلسلة النصية عنوان بريد إلكتروني صحيحًا (نسخة مبسطة):
\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string email = "user@example.com";\n // نمط للتحقق من البريد الإلكتروني (مبسط)\n std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})");\n\n if (std::regex_match(email, pattern)) {\n std::cout << "البريد الإلكتروني صحيح." << std::endl;\n } else {\n std::cout << "البريد الإلكتروني غير صحيح." << std::endl;\n }\n\n // التحقق من بريد إلكتروني غير صحيح\n std::string bad_email = "user@.com";\n if (std::regex_match(bad_email, pattern)) {\n std::cout << "البريد الإلكتروني صحيح." << std::endl;\n } else {\n std::cout << "البريد الإلكتروني غير صحيح." << std::endl;\n }\n\n return 0;\n}\n\nالمخرجات:
\nالبريد الإلكتروني صحيح.\nالبريد الإلكتروني غير صحيح.\n\nالشرح:
\n- \n
- نستخدم حرفية السلسلة النصية الخام
R"(...)"لتجنب الهروب من الخطوط المائلة العكسية. \n - الدالة
std::regex_matchترجعtrueفقط إذا كانت السلسلة النصية بأكملها تطابق النمط تمامًا. \n - النمط
[a-zA-Z0-9._%+-]+يعني "حرف واحد أو أكثر من المجموعة المحددة". \n
مثال 2: البحث عن سلسلة فرعية واستخراج البيانات (std::regex_search)
\n\nغالبًا ما نحتاج ليس فقط إلى التحقق، بل إلى العثور على جميع تكرارات النمط واستخراج أجزاء من السلسلة النصية. لهذا نستخدم std::regex_search في حلقة. في المثال التالي، سنجد جميع أرقام الهواتف بالتنسيق +7-XXX-XXX-XX-XX في النص ونستخرج رمز المشغل:
#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string text = "جهات الاتصال: +7-495-123-45-67 و +7-916-987-65-43. رقم إضافي: +7-495-111-22-33.";\n // النمط: +7-الرمز(3 أرقام)-... (مجموعات التقاط للرمز والباقي)\n std::rege