السلام عليكم
الدرس الحادي عشر والأخير : System.Text.RegularExpressions
مدة الدرس 30 دقيقة .
في الدرس الأخير يتوجب علينا توظيف القوالب والسلوكيات المتوفرة في VB.NET لتكون خاتمة لهذه السلسلة المتواضعه
فسنستهل حديثنا عن القالب Capture Class وهو يقوم بما تقوم به الأداة $ التي تم التطرق لها في الدرس الثامن
وهي عملية حفظ ما تطابق في المجموعة Group , إلا أنه يمتلك إلى خصائص وسلوكان تمكننا بسهولة التعامل مع المجموعات وقيمها.
كل خصائص هذا القالب هي من نوع Read only للقراءة فقط .
يتوجب علينا لتعريف القالب أن نقوم بتعريف مجموعة من نفس النوع وتعرف بـ CaptureCollection وهي كذلك قالب
مستقل بذاته . لنفترض أن لدينا نص بهذا الشكل
one = 1 two = 2 و نريد أن نعرف القيم التي تطابقت من خلال هذه الصيغة وهي
Dim RX As String = "(?<1>\d+)\s*" لنكتب المثال بهذا الشكل
txt2.Text = "one = 1 two = 2" Dim RX As String = "(?<1>\d+)\s*" Dim r As New Regex(RX, RegexOptions.IgnoreCase) Dim m As Match = r.Match(txt2.Text) While m.Success Dim cc As CaptureCollection = m.Captures Dim c As Capture For Each c In cc txt3.Text += c.Value() Next c m = m.NextMatch() End While
سيكون الناتج هو 1 و 2 لأننا نبحث عن تطابق أرقام فقط لا كلمات .
يتبين لنا من خلال هذا المثال البسيط أن الفائدة من القالب Capture هو معرفة ما تطابق
من الصيغة وهذا مفيد و مهم جداً لفهم آلية Regex ولمعرفة التطابق بشكل أغزر و أعمق .
القالب Group وهي المجموعة و لها Collection كقالب تعرف بـ GroupCollection
نستطيع اللف فيها و إظهار قيم المجموعات , كذلك نستطيع أن نظهر قيمة مجموعة
دون إستخدام الـ GroupCollection بأن نقوم بالتعامل مع العنصر Match مباشرتاً بهذا الشكل
txt2.Text = "one=1 two=2" Dim RX As String = "\w+=(\d)\s\w+=(\d)" Dim r As New Regex(RX, RegexOptions.IgnoreCase) Dim m As Match = r.Match(txt2.Text) Dim g1 As Group = m.Groups(1) Dim g2 As Group = m.Groups(2) txt3.Text = "Group 1 is: " & g1.ToString & vbCrLf txt3.Text += "Group 2 is: " & g2.ToString
سيكون الناتج في المجموعة الأول القيمة 1 و الثانية القيمة 2
الفائدة القصوى من هذا القالب معرفة قيمة مجموعة معينه كمثلاً المجموعة الأولى أو الثانية
ولهذا يتبين أن الفارق بينه وبين القالب Capture انه يمكن أن يكون خاص و مقيد
بينا Capture هو عام و مطلق .
القالب Match وله كذلك مجموعة تعرف بـ MatchCollection
نستطيع بهذا القالب معرفة هل تم التطابق من عدمه
كذلك نستطيع به أن نقوم بتكرار المطابقة , كما توضح لنا النصوص البرمجية التالية
Dim m As Match Dim rx As New Regex(str2) Dim Counter As Integer Result = String.Empty m = rx.Match(txt2.Text) Do While m.Success Result += m.Value.ToString & ControlChars.CrLf Counter += 1 m = m.NextMatch Loop Me.txt3.Text = Result & vbCrLf & " There are " & Counter & " HTML Tags Founded "
التحليل
الخاصية Success ترجع لنا قيمة منطقية أما True أو False وبها
نستطيع معرفة التطابق .
السلوك NextMatch يمكننا من تكرار المطابقة .
كذلك هنالك ما يعرف بـ MatchEvaluator Delegate وهو معلوم لدى الجميع أنه عبارة
عن Function يتم مناداتهِ كلما وقع حدث معين , هذا الـ Delegate مخصص لعملية الإستبدال
Replace , و يتم إستخدامه على النحو التالي
Dim StrRX, Str As String Str = "Arab_Team_Group" StrRX = "_" Dim rx As Regex = New Regex(StrRX) Dim EVl As MatchEvaluator = New MatchEvaluator(AddressOf ReplaceUnderScore) Str = rx.Replace(Str, EVl) MsgBox(Str) Public Function ReplaceUnderScore(ByVal m As Match) As String Return " " End Function
التحليل
أولاً لدينا نص بهذا الشكل Arab_Team_Group
ونريد حذف الـ underscore _ قمنا بتعريف MatchEvaluator
و أسندنا له الإجراء ReplaceUnderScore ليقوم بحذف الـ underscore كلما وجدت عن
طريق الوظيفة Replace بهذا الشكل Str = rx.Replace(Str, EVl)
كذلك نستطيع بدل هذه القصة كلها أن نقوم بالتالي فقط Str = rx.Replace(Str, " ")
ولا نحتاج إلى Delegate لإكمال المهمة .
تكمن فائدة الـ Delegate في التنظيم والترتيب Code Separation And Code Documentation
كذلك نستطيع من خلاله بعمليات التحقق قبل الإستبدال أو وضع شروط وفقاً لقيم ما .
هنالك القالب Regex وهو معلوم لمن تابع هذه السلسلة كونه صميم العمل core
ويتم تعريفه على النحو التالي
Dim StrRX As String = "^\d.*$" Dim rx As Regex = New Regex(StrRX)
هذا القالب لابد أن نقوم بعملية إستنساخ منه بإستخدام الكلمة المحجوزة New ثم أما أن نضع الـ Pattern مباشرةً أو
أن نضع متغير يحوي هذه الصيغة أو الـ Pattern
أو يتم تعريف هذا القالب مع إحدى قيم RegexOptions وهي عبارة عن Enumeration اي قيم معدودة و محصورة .
بهذا الشكل
rx = New Regex(str5, RegexOptions.None)
خصائص وسلوكيات Regex كالتالي
أولاً القالب Match يقبل النص المراد الإختبار عليه كممرر argument ويعود بقيمة من نوع قالب match
يتم إستخدامه بهذ الشكل
Result = String.Empty
Dim m As Match
Dim rx As New Regex("Color")
m = rx.Match("What is your Favorite Colour or Color ?")
Result = m.Value.ToString
Me.txt3.Text = Resultالوظيفة IsMatch تقبل النص المراد الإختبار عليه كممرر argument و تعود بقيمة منطقية
اما True تم التطابق أو False فشل التطابق , تستخدم بهذا الشكل
Result = String.Empty
Dim rx As New Regex("Color")
Result = rx.IsMatch("What is your Favorite Colour or Color ?")
Me.txt3.Text = Resultالقيمة العائدة في المتغير Result ستكون True وفقاً للمثال هذا .
ثم القالب MatchCollection ذكرنا في الأعلى وهذا مثال أخر عليها .
Result = String.Empty
Dim m As Match
Dim mc As MatchCollection
Dim rx As New Regex("")
mc = rx.Matches("What is your Favorite Colour or Color ?", "Colou?r")
Result = "how many time Matchs called " & mc.Count
Me.txt3.Text = Resultالنتيجة عدد مرات التطابق ستكون 2 .
وفي هذا القالب كذلك كل من GroupNameFromNumber و GroupNumberFromName لجلب اسماء أو أرقام
المجموعات في الصيغة , بهذا الشكل
txt2.Text = "a b"
Dim RX As String = "(?<Group1>A)"
Dim r As New Regex(RX, RegexOptions.IgnoreCase)
Dim m As Match = r.Match(txt2.Text)
Dim g1 As Group = m.Groups(1)
Dim g2 As Group = m.Groups(2)
txt3.Text = "Name of Group one is : " & r.GroupNameFromNumber(1).ToString & vbCrLf
txt3.Text += "The Position of Group1 is : " & r.GroupNumberFromName("Group1").ToStringو البقية تقريباً مررنا عليها من خلال الدروس .
القيم المعدودة هي كالتالي
RegexOptions.None وتعني أنه لا خيار محدد .
RegexOptions.Compiled وتعني أن الـ pattern
يترجم ككل وهذا يأخذ وقت في بدء التشغيل ولكنه أسرع
RegexOptions.CultureInvariant ويعني التعامل مع الـ pattern وفقاً للثقافة لبلدٍ ما.
وهي قيمة حساسة Case sensitive في الـ MSDN الكثير عنها للإطلاع .
RegexOptions.ECMAScript وهي والله أعلم من إسمها أنها تخص الـ J# لانه
ECMA منبع الـ jScript و الـ Action Script و تعني إستخدام نمط البرمجة على نحوها ونصوصها.
RegexOptions.ExplicitCapture وهي عملية إحكام على المجموعات بحيث يتم تجاهل اي مجموعة لا
تحوي اسم أو رقم يميزها عن بقية المجموعات الأخرى. شاهد المثال التالي
txt2.Text = "one=1 two=2" Dim RX As String = "\w+=(?<group1>\d)\s\w+=(?<2>\d)" Dim r As New Regex(RX, RegexOptions.ExplicitCapture) Dim m As Match = r.Match(txt2.Text) Dim g1 As Group = m.Groups(1) Dim g2 As Group = m.Groups(2) txt3.Text = "Group 1 is: " & g1.ToString & vbCrLf txt3.Text += "Group 2 is: " & g2.ToString
النتيجة ستكون 1 & 2
RegexOptions.IgnoreCase هذه القيمة تقوم بتجاهل الحساسية Case sensitive بحيث
يقبل كل من الحروف الصغيرة والكبيرة ولا فرق بينهما من حيث المطابقة . شاهد المثال التالي
txt2.Text = "a b" Dim RX As String = "(?<1>A)\s(?<2>B)" Dim r As New Regex(RX, RegexOptions.IgnoreCase) Dim m As Match = r.Match(txt2.Text) Dim g1 As Group = m.Groups(1) Dim g2 As Group = m.Groups(2) txt3.Text = "Group 1 is: " & g1.ToString & vbCrLf txt3.Text += "Group 2 is: " & g2.ToString
النتيجة ستكون a b رغم أن الـ pattern يحوي A B .
RegexOptions.IgnorePatternWhitespace تقوم بتجاهل الفراغات التي تتخلل ال pattern
كما تقوم بتمكين كتابة التعليقات خلال الصيغة بهذا الشكل
txt2.Text = "a b " Dim RX As String = "(?<1>a)\s(?<2>b)#here is letter b" Dim r As New Regex(RX, RegexOptions.IgnorePatternWhitespace) Dim m As Match = r.Match(txt2.Text) Dim g1 As Group = m.Groups(1) Dim g2 As Group = m.Groups(2) txt3.Text = "Group 1 is: " & g1.ToString & vbCrLf txt3.Text += "Group 2 is: " & g2.ToString
الناتج a و b رغم أن بعد الحرف b يوجد فراغ ولكن تم تجاهله .
كذلك هنالك تعليق بعد المجموعة الثانية بإستخدام الـ #
RegexOptions.Multiline تقوم بتغير نمط ^ بحيث يصبح له معنىً أخر وهو مطابقة بداية النص أو كل مقطع في النص
وينوب عن الأداة (?m)
للمزيد راجع الدرس السادس , ومثاله كالتالي :
Const str3 As String = "^'.+$"
Dim m As Match
Dim rx As New Regex(str3, RegexOptions.Multiline)
Dim Counter As Integer
m = rx.Match(txt2.Text)
Do While m.Success
Counter += 1
m = m.NextMatch
Loop
MessageBox.Show(" There are " & Counter & " Comments in this String ")RegexOptions.RightToLeft وتعني بدء المطابقة من اليمين إلى الشمال بالنسبة للنص المراد
إختبار المطابقة عليه وليس الصيغة بذاتها . مثال ذلك
Result = String.Empty Dim m As Match Dim rx As Regex Select Case whichString Case 1 rx = New Regex(str1) Case 2 ' RightToLeft Option let the Regex to Start Matching ' From the Right Side will starts Match the ? then the Color rx = New Regex(str2, RegexOptions.RightToLeft) End Select m = rx.Match(Me.txt2.Text) Result = m.Value.ToString Me.txt3.Text = Result
RegexOptions.Singleline وهي إرجاع معنى الـ ^ على اساس أنه يقوم بمطابقة أولا النص فقط
وهو عكس RegexOptions.Multiline تماماً وهو كذلك مقدم على الأداة (?m) بحيث لو تم تعريفها في
الصيغة ثم قمنا بإستخدام القيمة SingleLine سيتم إعتماده و تجاهل الأداة (?m) . مثالهُ كالتالي
Const str3 As String = "(?m)^'.+$"
Dim m As Match
Dim rx As New Regex(str3, RegexOptions.Singleline)
Dim Counter As Integer
m = rx.Match(txt2.Text)
Do While m.Success
Counter += 1
m = m.NextMatch
Loop
MessageBox.Show(" There are " & Counter & " Comments in this String ")الناتج سيكون تم العثور على تعليق واحد فقط .
أخيراً القالب RegexCompilationInfo نستطيع به معرفة كل من
1. الصيغة ,اي شكل التركيبة المتضمنه فيها.
2. اسم يعنون للصيغة (من حيث الترتيب والتنسيق)
3. هل هو عام أو خاص عن طريق القيمة الأخيرة من هذا القالب أما True أو False
4. معرفة اسم الحاوية NameSpace إذا كنت تضع الصيغ مرتبة في حاويات
5. معرفة نوع الخيار Options الذي يتضمن هذه الصيغة مثل SingleLine أو غير ذلك .
شاهد المثال التالي .
Dim rxInfo As New RegexCompilationInfo("^\d+$", _
RegexOptions.Singleline, "CheckNumber", _
"myNameSpace", True)
MsgBox(rxInfo.Pattern.ToString())
MsgBox(rxInfo.Name.ToString())
MsgBox(rxInfo.IsPublic.ToString())
MsgBox(rxInfo.Namespace.ToString())
MsgBox(rxInfo.Options.ToString())أجوبت الدروس السابقة
الدرس الثاني :
وهنا سؤال يطرح نفسه : في ماذا يستخدم Regex الأداة \ Backslash ؟
يستخدم الـ escaping backslash \ أما لأخطار Regex بأن هذه القيمة نصية وليست أداة أو أن هذا الحرف
أداة وليس حرف فمثلاً \. يراد بها النقطة و . يراد بها خانة واحدة
كذلك \d يراد بها رقم من صفر إلى تسعة و d يراد به حرف الـ d نفسه .
الدرس الثالث :
السؤال الأول : قم ببناء صغية لا تقبل الرقم سبعة 7
[^7]
السؤال الثاني : لو بنينا صيغة بهذا الشكل [A-z]
إضافة إلى الأحرف الكبيرة والصغيرة سيكون كل من [ \ ] ^ _ `
السؤال الثالث والأخير : قم ببناء صغية لا تقبل المسافة , وفقاً لما تعلمناه
Const str1 As String = "^[^ ]$"
الدرس الرابع :
سؤال هذا الدرس : أكتب الصيغة المناسبة لمطابقة القيمة التالية خانة تقبل من واحد إلى عشرة على واحد إلى عشرة
لا تقبل الصفر ولا يمكن أن تكون فارغة . مثلاً 1\10 لكن ليس 0\1 أو Null
"^([1-9]|10)\\([1-9]|10)$"
الدرس الخامس :
1 - yes
2 - yes
3 - yes
4 - No it means single digit or + character
5 - No it's limited to 249 only
6 - No it means single digit and {}
الدرس السادس :
ما هي الأخطاء المرتكبة في هذه التركيبة النصية
Const str3 As String = "\A'.+\Z"
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim m As Match
Dim rx As New Regex(str3, RegexOptions.Singleline)
Dim Counter As Integer
m = rx.Match(txt2.Text)
Do While m.Success
Counter += 1
m = m.NextMatch
Loop
MessageBox.Show(" There are " & Counter & " Comments in this String ")
End Subالجواب : لا توجد أخطاء مرتكبة في الصيغة .
الدرس السابع :
1 - ^([1-9]{1,2}-){2}[1-9]{1,2}$
2 - ^([1-9]{1,2}-){5}[1-9]{1,2}$ or ^(([1-9]{1,2}-){2}){2}[1-9]{1,2}$
3 - Match the () characters
4 - Wrong Pattren because if you not use ^ at the beginning of the pattren then it means as the repeator tool
for instance ^[1-9]^2$ means repeat digit twice from 1 to 9 matches 11 22 and etc... this concept
does not impact on VB.NET , While Does on Other languages , so What does this pattren mean ?
In VB.NET the ^ tool has several meaning one it matchs the begining of the string or negates mean
if enclosed within [] , so whereas both of them not used then it has wrong meaning
and it acts as the begining Tool in the wrong position. God knows.
الدرس الثامن :
1 - No we use \2
2 - No we either write ?<Nums> or ?'Nums'
3 - No we refer to the Group name by single Qutation 'myGroup'
4 - NO After Starting ( Group
5 - NO we don't need Back Reference
6 - No we use $3
7 - <a([1-6])>.*?</a\1>
الدرس التاسع :
question 1 Answer 3
question 2 Answer 2
question 3 Answer 1
question 4 Answer (?<=<a[1|2|3|4]>).+(?=</a[1|2|3|4]>)
question 5 Answer ^\d{5,6}|(\d{1,6}(?=-)-\d{4})
الدرس العاشر :
Question 1 Answer Wrong the Correct Pattren is (r|h|s)ide
Question 2 Answer Wrong the Correct Pattren is (my|by)
Question 3 Answer Wrong it's Correct pattren with Group and gives Expected Result
Question 4 Answer Wrong it looks for the word Color, RightToLeft Doesn't effect on Pattrens
it effects on the text that the Regex from where it begins to matchs.
Question 5 Answer Wrong the Correct Conditions Tools are ? and |
Question 6 Answer Wrong the Correct Pattren is (my name is :?)
لا توجد أسئلة في هذا الدرس والله يوفقكم لما فيه الخيرو البركة
السلام عليكم .