التعبيرات النمطية في C#: دليل كامل للمبتدئين
\nالتعبيرات النمطية (regular expressions, regex) هي أداة قوية للبحث والاستبدال والتحقق من السلاسل النصية وفق نمط معين. في C# (.NET) يتم التعامل مع التعبيرات النمطية من خلال مساحة الأسماء System.Text.RegularExpressions. ستساعدك هذه المقالة على إتقان الأساسيات: من إنشاء أبسط الأنماط إلى استخدام جميع إمكانيات فئة Regex.
1. أساسيات العمل مع Regex في C#
\nللبدء، قم بتضمين مساحة الأسماء:
\nusing System.Text.RegularExpressions;\nتوفر فئة Regex طرقًا ثابتة وطرقًا خاصة بالكائن. أبسط طريقة للتحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة فرعية وفق نمط معين هي طريقة IsMatch:
string text = "مرحبًا، بريدي الإلكتروني: test@example.com";\nstring pattern = @"\\w+@\\w+\\.\\w+"; // نمط بسيط للبريد الإلكتروني\n\nbool hasEmail = Regex.IsMatch(text, pattern);\nConsole.WriteLine(hasEmail); // True\nتحليل النمط:
\n- \n
\\w+— حرف أو أكثر من الحروف أو الأرقام أو الشرطات السفلية \n@— رمز "@" \n\\.— نقطة هاربة (بدون الهروب، تعني النقطة "أي حرف") \n
للاستدعاءات المتكررة، من الأفضل إنشاء كائن Regex لتجنب إعادة ترجمة النمط:
Regex emailRegex = new Regex(@"\\w+@\\w+\\.\\w+");\nConsole.WriteLine(emailRegex.IsMatch("admin@site.ru")); // True\n\n2. البحث عن جميع التطابقات: Match وMatchCollection
\nتعيد طريقة Match أول تطابق، بينما تعيد Matches جميع التطابقات كمجموعة MatchCollection. يحتوي كل كائن Match على معلومات حول السلسلة الفرعية التي تم العثور عليها وموقعها وطولها.
مثال: استخراج جميع الأرقام من سلسلة نصية
\nstring data = "في عام 2023 كان هناك 15 حدثًا، وفي 2024 — 23 بالفعل.";\nstring numberPattern = @"\\d+"; // رقم واحد أو أكثر\n\nMatchCollection matches = Regex.Matches(data, numberPattern);\n\nforeach (Match match in matches)\n{\n Console.WriteLine($"تم العثور على: {match.Value} في الموضع {match.Index}");\n}\n// الإخراج:\n// تم العثور على: 2023 في الموضع 2\n// تم العثور على: 15 في الموضع 20\n// تم العثور على: 2024 في الموضع 34\n// تم العثور على: 23 في الموضع 47\nالعمل مع المجموعات (Group). تسمح المجموعات باستخراج أجزاء من التطابق. على سبيل المثال، عند البحث عن تاريخ بتنسيق "يوم.شهر.سنة" يمكن الحصول على اليوم والشهر والسنة بشكل منفصل:
\nstring input = "اليوم 25.12.2024";\nstring datePattern = @"(\\d{2})\\.(\\d{2})\\.(\\d{4})";\n\nMatch match = Regex.Match(input, datePattern);\nif (match.Success)\n{\n Console.WriteLine($"اليوم: {match.Groups[1].Value}"); // 25\n Console.WriteLine($"الشهر: {match.Groups[2].Value}"); // 12\n Console.WriteLine($"السنة: {match.Groups[3].Value}"); // 2024\n}\nيتم ترقيم المجموعات بدءًا من 1 (المجموعة 0 هي التطابق بأكمله). المجموعات المسماة أسهل في القراءة:
\nstring namedPattern = @"(?<day>\\d{2})\\.(?<month>\\d{2})\\.(?<year>\\d{4})";\nmatch = Regex.Match(input, namedPattern);\nConsole.WriteLine(match.Groups["day"].Value); // 25\n\n3. إمكانيات متقدمة: الاستبدالات والخيارات
\nاستبدال النص باستخدام Regex.Replace. لا يسمح فقط بحذف أو استبدال السلسلة الفرعية، بل يسمح أيضًا باستخدام المجموعات في سلسلة الاستبدال:
\nstring phone = "+7 (123) 456-78-90";\n// إزالة كل شيء ما عدا الأرقام\nstring clean = Regex.Replace(phone, @"[^\\d]", "");\nConsole.WriteLine(clean); // 71234567890\n\n// تغيير التنسيق: (123) 456-78-90 → 123-456-7890\nstring formatted = Regex.Replace(phone, \n @"\\((\\d{3})\\)\\s*(\\d{3})-(\\d{2})-(\\d{2})",\n "$1-$2-$3$4");\nConsole.WriteLine(formatted); // 123-456-7890\nخيارات مهمة (RegexOptions):
\n- \n