التعبيرات النمطية في C++ مع أمثلة: من الأساسيات إلى التطبيق العملي
التعبيرات النمطية (regex) هي أداة قوية للبحث عن أجزاء النص واستخراجها واستبدالها وفقًا لنمط معين. في لغة C++، ظهر دعم التعبيرات النمطية في معيار C++11 وتم تنفيذه في المكتبة <regex>. في هذه المقالة، سنستعرض أمثلة عملية لاستخدام std::regex ستساعدك على معالجة السلاسل النصية بكفاءة في مشاريعك.
1. أساسيات std::regex: الإنشاء والبحث البسيط
للعمل مع التعبيرات النمطية في C++، تُستخدم ثلاث فئات رئيسية: std::regex (النمط)، std::smatch (النتيجة لسلسلة نصية)، و std::sregex_iterator (مكرر للتطابقات المتعددة).
مثال 1: التحقق من تطابق سلسلة نصية مع نمط
#include <iostream>#include <regex>#include <string>
int main() { std::string email = "user@example.com"; // نمط للتحقق من البريد الإلكتروني (مبسط) std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})"); if (std::regex_match(email, pattern)) { std::cout << "البريد الإلكتروني صحيح!" << std::endl; } else { std::cout << "البريد الإلكتروني لا يتوافق مع التنسيق." << std::endl; } return 0;}تتحقق الدالة std::regex_match مما إذا كانت السلسلة النصية بأكملها تطابق النمط بالكامل. لاحظ استخدام R"(...)" وهي سلسلة نصية خام (raw string literal) تسمح بعدم الحاجة إلى إفلات الخطوط المائلة العكسية.
مثال 2: البحث عن سلسلة فرعية
#include <iostream>#include <regex>#include <string>
int main() { std::string text = "رقمي: +7 (123) 456-78-90. اتصل بي!"; std::regex phone_pattern(R"(\\+7\\s?\\(\\d{3}\\)\\s?\\d{3}-\\d{2}-\\d{2})"); std::smatch match; if (std::regex_search(text, match, phone_pattern)) { std::cout << "تم العثور على الرقم: " << match.str() << std::endl; std::cout << "الموضع: " << match.position() << std::endl; } else { std::cout << "لم يتم العثور على الرقم." << std::endl; } return 0;}تبحث std::regex_search عن أول تطابق مع النمط في السلسلة النصية. يتم حفظ النتيجة في كائن std::smatch، والذي يمكن من خلاله استخراج السلسلة الفرعية التي تم العثور عليها وموضعها.
2. استخراج البيانات باستخدام المجموعات (capturing groups)
تسمح المجموعات باستخراج أجزاء منفصلة من التطابق. يتم الإشارة إليها باستخدام الأقواس الدائرية ().
مثال 3: تحليل التاريخ
#include <iostream>#include <regex>#include <string>
int main() { std::string date = "اليوم 15.04.2025"; std::regex date_pattern(R"((\\d{2})\\.(\\d{2})\\.(\\d{4}))"); std::smatch match; if (std::regex_search(date, match, date_pattern)) { std::cout << "التاريخ الكامل: " << match[0] << std::endl; std::cout << "اليوم: " << match[1] << std::endl; std::cout << "الشهر: " << match[2] << std::endl; std::cout << "السنة: " << match[3] << std::endl; } return 0;}مثال 4: استخراج جميع التطابقات باستخدام المكرر
#include <iostream>#include <regex>#include <string>
int main() { std::string log = "ERROR: الملف غير موجودWARNING: شحن البطارية منخفضINFO: العملية مكتملةERROR: انتهاء مهلة الاتصال"; std::regex error_pattern(R"(^ERROR:\\s*(.+)$)"); // استخدام std::sregex_iterator لتكرار جميع الأسطر auto words_begin = std::sregex_iterator(log.begin(), log.end(), error_pattern); auto words_end = std::sregex_iterator(); std::cout << "تم العثور على