الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

البحث عن الكلمات والنصوص المقتبسة

مغلق
بدأه محمد سامر أبو سلو في 25 أكتوبر 2006 · 0 رد · 901 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1

إحدى العمليات الشائعة للتعابير النظامية 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

مترجم للفائدة

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

هذا الموضوع مغلق.

مواضيع مشابهة