التعبيرات النمطية في Kotlin مع أمثلة: من الناحية العملية
\n\nالتعبيرات النمطية (regex) هي أداة قوية للعمل مع السلاسل النصية. في Kotlin، تم تنفيذها بناءً على فئات Java Pattern و Matcher، ولكن مع إضافة اللغة لامتداداتها المريحة والسكر النحوي الخاص بها. في هذه المقالة، سنشرح كيفية استخدام التعبيرات النمطية في Kotlin من خلال أمثلة حقيقية: من البحث البسيط إلى الاستبدال وتقسيم السلاسل.
أساسيات الصياغة: الإنشاء والتجميع
\n\nفي Kotlin، يمكن إنشاء تعبير نمطي بطريقتين: من خلال الفئة Regex أو باستخدام سلسلة نصية مع نمط. الطريقة الأولى هي المفضلة لأنها توفر المزيد من الدوال.
// الطريقة 1: من خلال الفئة Regex\nval regex = Regex("\\\\d+") // رقم واحد أو أكثر\n\n// الطريقة 2: من خلال سلسلة نصية (غير موصى بها للتعبيرات المعقدة)\nval pattern = "\\\\d+".toRegex()\n\nلاحظ الشرطة المائلة المزدوجة للهروب: \\\\d — هذا هو الهروب لـ Java/Kotlin للحصول على الرمز \\d في السلسلة. للتبسيط، يدعم Kotlin السلاسل النصية الخام (الاقتباسات الثلاثية """)، حيث لا يكون الهروب مطلوبًا:
val regex = Regex("""\\d+""") // سلسلة خام — لا حاجة لتكرار الشرط المائلة العكسية\n\nيمكنك أيضًا إضافة علامات، على سبيل المثال، RegexOption.IGNORE_CASE:
val regex = Regex("kotlin", RegexOption.IGNORE_CASE)\n\nالبحث والتحقق من التطابقات
\n\nالعمليات الأكثر شيوعًا هي التحقق مما إذا كانت السلسلة تحتوي على سلسلة فرعية تطابق النمط، وإيجاد جميع التطابقات.
\n\nالتحقق من وجود تطابق: containsMatchIn
\n\nval text = "رقمي: 123-45-678"\nval digitRegex = Regex("""\\d+""")\n\nif (digitRegex.containsMatchIn(text)) {\n println("النص يحتوي على أرقام!")\n}\n\nالبحث عن أول تطابق: find
\n\nval result = digitRegex.find(text)\nprintln(result?.value) // سيطبع: 123\n\nالبحث عن جميع التطابقات: findAll
\n\nval allMatches = digitRegex.findAll(text)\nallMatches.forEach { match ->\n println("تم العثور على: ${match.value}") // 123, 45, 678\n}\n\nتقوم الدالة findAll بإرجاع تسلسل من كائنات MatchResult. يحتوي كل كائن من هذا القبيل ليس فقط على التطابق نفسه (.value)، ولكن أيضًا على موضعه في السلسلة (.range).
العمل مع مجموعات الالتقاط
\n\nمجموعات الالتقاط هي أجزاء من النمط محصورة بين أقواس دائرية. تسمح باستخراج أجزاء محددة من البيانات. على سبيل المثال، سنقوم بتحليل البريد الإلكتروني إلى اسم المستخدم والمجال:
\n\nval email = "user@example.com"\nval emailRegex = Regex("""(.+)@(.+)""")\nval matchResult = emailRegex.find(email)\n\nif (matchResult != null) {\n val (username, domain) = matchResult.destructured\n println("اسم المستخدم: $username") // user\n println("المجال: $domain") // example.com\n}\n\nالتركيب destructured يقوم بتقسيم المجموعات إلى متغيرات بشكل مريح. إذا كان هناك المزيد من المجموعات، يمكن الوصول إليها عن طريق الفهرس:
val fullMatch = matchResult.value // user@example.com\nval group1 = matchResult.groupValues[1] // user\nval group2 = matchResult.groupValues[2] // example.com\n\nالمجموعات المسماة (Kotlin 1.7+)
\n\nبدءًا من Kotlin 1.7، يمكن استخدام المجموعات المسماة:
\n\nval namedRegex = Regex("""(?<name>\\w+)@(?<domain>\\w+\\.\\w+)""")\nval match = namedRegex.find("contact@kotlin.org")\nif (match != null) {\n println(match.groups["name"]?.value) // contact\n println(match.groups["domain"]?.value) // kotlin.org\n}\n\nاستبدال النص باستخدام replace
\n\nتسمح الدالة replace باستبدال جميع التطابقات بسلسلة جديدة. في نمط الاستبدال، يمكن الإشارة إلى مجموعات الالتقاط عن طريق