إحدى العمليات الشائعة للتعابير النظامية Regular Expressions هي تقسيم سلسلة نصية طويلة إلى كلمات وهي تعتبر أبسط عملية يمكن أن تقوم بها باستخدام التعابير النظامية
Dim text As String = "A word with àccéntèd vowels, and the 123 number." Dim pattern As String pattern = "\w+" For Each m As Match In Regex.Matches(text, pattern) Console.WriteLine(m.Value) Next
والمشكلة في هذا المثال المبسط في انه يحتوي على أرقام وشرطات في مجموعة Collection النتائج وق لا ترغب بذلك وستكون المحاولة الأفضل على الشكل
pattern = "\w+"
وهذا سيعمل بشكل أفضل ولكنه سيفشل بإضافة الكلمات كاملة إذا كانت تحتوي على حروف مشددة accented characters أو حروف من لعات أخرى كاليونانية مثلا وتحت النسخ السابقة من الفريموورك يمكنك أن تحل هذه المشكلة باستخدام \p والذي يمكنك كن استخدام محارف يونيكود فعلى سبيل المثال \p{Ll} يمثل أي محرف صغير بينما \p{Lu} يمثل أي محرف كبير وبذلك يكون حل المشكلة كالتالي
pattern = "(\p{Lu}|\p{Ll})+"تم تقديم ميزة طرح فئات المحارف في الفريموورك 2.0 لتقدم حلا جديدا لهذه المشكلة معتمدا على حقيقة أنه يمكنك طرح الأرقام والشرطات من مجال المحارف المعبر عنها بواسطة \w
pattern = "[\w-[0-9_]]+"
وعندما تستخرج الكلمات غالبا ما تريد اسقاط كلمات الضوضاء مثل The و a و an وما مثل ذلك حيث يمكنك اسقاط هذه الكلمات ضمن حلقة For … Each ولكن الكثر أناقة هو ترك التعابير النظامية لتقوم بالتخلص منهم
pattern = "\b(?!(the|a|an|and|or|on|of|with)\b)\w+"
text = "A fox and another animal on the lawn"
For Each m As Match In Regex.Matches(text, pattern, RegexOptions.IgnoreCase)
Console.Write("{0} ", m.Value) ' => fox another animal lawn
Nextالتعبير \w في المثال السابق يحدد أننا نبحث عن كلمة بينما التعبير (?!...]B) يحدد أن النتيجة يجب أن لا تحتوي أحد كلمات الضوضاء وبذلك تكون النتيجة بأناقة هي أن النموذج pattern سيطابق جميع الكلمات عدا تلك الموجودة في قائمة الضوضاء.
مشكلة أخرى شائعة وهي عندما تريد أن تعتبر نص مقتبس Quoted ككلمة واحدة وذكل كمثل عندما تقوم بمعالجة أمر يتم تمريره عبر سطر الأوامر والمثال التالي يستخجم تعبيرا نظاميا يطابق كلمة مفردة أو نص مضمن ضمن علامات اقتباس مفردة أو مزدوجة
' For simplicity's sake, use \w+ to match an individual word. pattern = "(?<q>[""']).*?\k<q>|\w+"
لاحظ أن .*? تقوم بعمل مطابقة كسولة بحيث تطابق أي محرف بين علامات الاقتباس بينما لا تطابق علامات الاقتباس للإغلاق
ربما ترغب أحيانا باستخراج كلمات فريدة مثلا عمدما تريد عمل قاموس بجميع الكلمات الموجودة في ملف نصي حيث يمكن أن يشكل جدول هاش Hashtable حلا لتذكر الكلمات التي تم إيجادها حتى الآن
Dim text As String = "one two three two zone four three"
Dim re As New Regex("\w+")
Dim words As New Hashtable()
For Each m As Match In re.Matches(text)
If Not words.Contains(m.Value) Then
Console.Write("{0} ", m.Value)
words.Add(m.Value, Nothing)
End If
Nextوبشكل آخر يمكنك تحقيق ذلك باستخدام التعبيرات النظامية
pattern = "(?<word>\b\w+\b)(?!.+\b\k<word>\b)" For Each m As Match In Regex.Matches(text, pattern) Console.Write(m.Value & " ") Next
التعبير (?<word>]b]w+]B) يطابق سلسلة محارف وأرقام (\w) على حدود الكلمة (\b) وتحدد في هذا السياق الاسم "word" والتركيب (?!) يعني أن الكلمة يجب أن لاتطابق كلمة تم إيجادها سابقا ( المرجع الخلفي \k<word> ) وحتى إذا كانت هناك محارف أخرى في المنتصف ممثلة بالتسلسل .+ وبتعبير واضح يكون التعبير النظامي يعني طابق أي كلمة في النص بحيث أن لاتكون متبوعة بورود آخر نفس الكلمة أو ببساطة أكثر احصل على الكلمات التي لها ورود واحد في الوثيقة أو آخر ورود للكلمة المكررة وبهذا سيتم إيجاد كافة الكلمات الفريدة بصورة صحيحة
لاحظ أن المحارف \b في التعبيرات النظامية تمنع المطابقات الجزئية فــ one لاتطابق zone وبتعبير نظامي مختلف قليلا يمكنك إيجاد الكلمات المكررة في الوثيقة
pattern = "(?<word>\b\w+\b)(?=.+\b\k<word>\b)"
حيث أن (?=) يعني أن الكلمة المطابقة يجب أن تكون متبوعة بورود آخر لها ومع أن تقنيات التعبيرات النظامية أنيقة فإن التعبير (?=) الخاص بالنظر للأمام يجعلها غير كفؤة نسبيا فمثلا عند معالجة مصدر نصي يحتوي على حوالي مليون حرف سيكون استخدام النعبيرات النظامية أبطأ بحوالي 8 مرات من التقنية التي تستخدم جدول هاش hashtable مساعد لكي يحتفظ بسجل عن الكلمات التي تم إيجادها سابقا
نوع أخير من البحث عن الكلمات يمكن أن نتحدث عنه هنا هو البحث التقريبي وذلك عندما تبحث عن نصين يجب إيجادهما قريبين من بعضهما في النص المصدر بحيث لايكون أمثر من عدد N من الكلمات بفصل بينهما فعلى سبيل المثال النص "one two three two zone four three" هو المصدر فالبحث التقريبي للكلمات "one" و "four" والعدد N مساوي 4 سيتم بنجاح بينما سوف يفشل إذا كان العدد N مساوي لـ 3 ويمكن أن يكون نموذج البحث ببساطة كالمثال
pattern = "\bone(\W+\w+){0,4}\W+\bfour\b"
If Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase) Then
' At least one occurrence of the words "one" and "four"
' with four or fewer words between them.
End Ifويمكن أن تحدد دالة function تأخذ سلسلة نصية كمدخل وكلماتن ورقم يمثل المسافة الأعظمية بينهما وتعيد خرج بشكل مجموعة مطابقات MatchCollection
Function ProximityMatches(ByVal text As String, ByVal word1 As String, _
ByVal word2 As String, ByVal maxDistance As Integer) As MatchCollection
Dim pattern As String = "\b" & word1 & "(\W+\w+){0," & maxDistance.ToString() _
& "}\" & "W+\b" & word2 & "\b"
Dim re As New Regex(pattern, RegexOptions.IgnoreCase)
Return re.Matches(text)
End Functionوبهذا تصبح قطعة الكود السابقة بالشكل
Dim mc As MatchCollection = ProximityMatches(text, "one", "four", 4) If mc.Count > 0 Then … End If
مترجم للفائدة