![]() |
|
[مشروع] البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - نسخة قابلة للطباعة +- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb) +-- قسم : قسم لغة الفيجوال بيسك VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=182) +--- قسم : قسم امثلة ومشاريع VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=188) +--- الموضوع : [مشروع] البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) (/showthread.php?tid=36456) |
البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - Anas Mahmoud - 19-09-20 بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته كان الاخ عبد الهادي قد طرح تساؤل حول البحث عن الكلمات داخل نص عربي يحتوي على حركات فتحة وضمة وهكذا ، وكان سؤالا هامة جدا وجيدا للغاية وكنت قد توصلت للحل باستخدام Regex ووعدت بان اقوم بشرح الموضوع بشكل اكبر نبدأ على بركة الله تقديم للمشكلة : تشكيل الحروف يمثل مشكلة عند البحث في الكلمات ، لان التشكيل نفسه يعتبر حرفا ، مثلا في الآية : الْحَمْدُ لِلَّهِ الَّذِي أَنْزَلَ عَلَىٰ عَبْدِهِ الْكِتَابَ وَلَمْ يَجْعَلْ لَهُ عِوَجًا ۜ اذا اردت البحث عن الكلمة "الحمد" فان الطريقة التقليدية IndexOf() مثلا فانها لن تنجح ، الكلمة التي تريد البحث عنها : الحمد : ا - ل - ح - م - د الكلمة الموجودة في الاية : ا - ل - ْ - ح - َ - م - ْ - د - ُ ما يقوم به IndexOf هو مقارنة حرف حرف من الكلمتين لايجاد تطابق ، وبالتالي لن ينجح الامر عند وجود تشكيل نحتاج طريقة ما للبحث ، بحيث نخبرها اننا نقبل اي من حروف التشكيل بعد كل حرف من الكلمة المطلوبة ، هنا يأتي دور Regex تقديم Regex : التعابير النمطية او القياسية او Regular Expression هي طريقة للبحث داخل نصوص بشكل رئيسي ، باستخدام تعابير تأخذ شكل معين لتحديد طريقة البحث المطلوب ، وهي طريقة جميلة جدا وعملية جدا وسريعة جدا فيما يتعلق بالوقت لست بصدد شرح Regex هنا ، يمكنك ان تجد معلومات اكثر عنها من هنا : http://vb4arb.com/vb/showthread.php?tid=467 https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=netcore-3.1 ولكن سأشرح ما سنحتاجه فقط . استخدم الموقع التالي للتجربة : https://regex101.com/r/euj8kG/1 الفئة System.Text.RegularExpressions.Regex تحتوي على دالة Matches التي تعيد MatchCollection يمثل المطابقات في النص المطلوب البحث فيه ، تقبل مدخلان : الاول : النص المطلوب البحث بداخله الثاني : تعبير Regex المستخدم في البحث ، ونحتاج منه الآتي : الكلمات الحرفية : في تعبير Regex اذا اردت البحث عن حروف ما بعينها بنفس الترتيب ، فعليك وضعها كما هيا في التعبير : التعبير التالي يبحث عن كلمة vb4arab كود : vb4arabالاختيار بين مجموعة حروف : اذا اردت اختيارا من بين اكثر من حرف ، يعني اما هذا او هذا او هذا تضعه بين اقواس مربعة [] في المكان الذي تريده : التعبير التالي يبحث عن الكلمات vb4arab و vb3arab و vb2arab : كود : vb[234]arab ويمكن استخدام - للدلالة على المدى من كذا الى كذا : كود : vb[2-4]arabالدلالة على التكرار : اذا اردت ان يكون الحرف اختياري ويمكن تكراره اكثر من مرة استخدم * بعد الحرف المطلوب : التعبير التالي يبحث عن vb4arb و vb4araaaaab و vb4arab و .... كود : vb4ara*bويمكن استخدامها مع اختيار من الحروف التعبير التالي يبحث عن vb4arab و vb4323243343323223arab و vbarab و .... ايضا : كود : vb[2-4]*arabمجموعات الالتقاط : فرضا انت تبحث عن نص بشرط ما ، ولكنك لاتريد فعلا ان ترجع بالنص باكمله بل تريد جزء منه فقط كان تبحث عن كلمتين مكررتين بعد بعضهما مباشرة وتريد الكلمة فقط ، هذه فائدة مجموعات الالتقاط Capture group التعبير التالي نفس التعبير السابق ولكنننا نضع الارقام في مجموعة نسميها x لكي نستعيدها مستقبلا : كود : vb(?<x>[2-4]*)arabاستخدام الحروف بكود unicode : اذا حاولت وضع التشكيل في الكود فانه على الارجح لن يكتب ، بدلا من ذلك نستخدم التعبير بكود الحرف unicode قائمة بيونيكود الحروف العربية : https://en.wikipedia.org/wiki/Arabic_script_in_Unicode التعبير التالي يبحث عن حرف ال v والذي له الكود U+0056 : كود : \u0056الخطة : الان يجب ان نحدد الاهداف : 1. نريد البحث عن الكلمات التي تحتوي على النص المدخل من المستخدم مع الاخذ بالاعتبار التشكيل 2. نريد ملي ال ListBox بنتائج البحث 3. نريد تلوين النص المدخل فقط من المستخدم ( ليس الكلمة كلها ) في كل المواقع الموجودة في النص الاصلي 4. عند اختيار المستخدم عنصر من ال ListBox يقوم البرنامج بالقفز الى موقعه في النص الاصلي التصميم : [attachment=25727] الكود : الدوال والاجرائات : سنعرف بعض الدوال لتسهيل العملية ، الدالة SearchArabic : عصب الكود الاساسي ، سنقوم فيها باجراء عملية البحث واعادة IEnumerable(Of Match) تمثل نتائج البحث لاستخدامها لاحقا ، ببساطة ، تأخذ النص المطلوب البحث عنه ، ونص البحث : كود : Function SearchArabic(Text As String, Word As String) As IEnumerable(Of Match)طيب الان ماذا نريد ان نفعل ؟ نريد ان نكوّن نص التعبير ، ببساطة نأخذ كل حرف ونضيف بعده القيمة [\u064B-\u0652]* التي تمثل اي من حروف التشكيل ، اختياري وقابل للتكرار كود : Dim expression As String الان نحن نبحث عن الحروف المدخلة من المستخدم فقط وسط التشكيل وهذا شيء جميل لكن كيف نستخرج الكلمة كاملة ؟ الامر بغاية البساطة ، نخبره بان يحضر ايضا اي عدد من الحروف العربية قبل هذه الحروف التي نبحث عنها وكذلك اي عدد من الحروف العربية بعد هذه الحروف التي نبحث عنها للتوضيح : (اي عدد من الحروف العربية)(حروف البحث)(اي عدد من الحروف العربية) مدى الحروف العربية هو من U+0600 الى U+06FF كود : Dim expression As String = "[\u0600-\u06FF]*"الان نحن جاهزون للبحث عن الكلمة باكملها ،نريد ان نضع الحروف المدخلة من المستخدم في مجموعة ونضع لها اسم input حتى نتمكن من الحصول عليها لاحقا : كود : Dim expression As String = "[\u0600-\u06FF]*(?<input>"الان المتغير expression اصبح يحمل نص التعبير واصبح جاهزا لعملية البحث : كود : Return Regex.Matches(Text, expression).Cast(Of Match)نجري عملية البحث من الدالة Regex.Matches ونقوم بتحويل النتائج الى IEnumerable(Of Match) عن طريق Cast(Of Match) يصبح كود الدالة كاملا : كود : Function SearchArabic(Text As String, Word As String) As IEnumerable(Of Match)للتجربة على كلمة "من" : https://regex101.com/r/QZKLfk/1 الإجراء ColorResults : نقوم فيه بتلوين نتائج البحث من مدخل المستخدم فقط وليس الكلمة كاملة ، لفعل ذلك نمر على نتائج البحث كلها ونختار المجموعة التي سميناها input ونلون منها مدخلات الاجراء: RichTextBox الذي به النص ، IEnumerable(Of Match) نتائج البحث ، ProgressBar اختياري لعرض نتائج البحث نستفيد من الخصائص داخل كائن ال Group ايضا مثل Index الذي يمثل بداية المجموعة داخل النص الاصلي و Length طول المجموعة كود : Sub ColorResults(richTextBox As RichTextBox, matches As IEnumerable(Of Match), Optional ProgressBar As ProgressBar = Nothing)بكل بساطة نمر على نتائج البحث ، لكل نتيجة نستخرج منها المجموعة "input" ، نقوم بتحديد المجموعة من ال RichTextBox وتلوينها بالاصفر نقوم بزيادة ال ProgressBar الإجراء FillListBox : نقوم بملئ الليست بوكس به عن طريق ToList السحرية ! المدخلات : ListBox المطلوب ملئه ، و IEnumerable(Of Match) نتائج البحث : كود : Sub FillListBox(matches As IEnumerable(Of Match), ListBox As ListBox)الإجراء PopulateResults : نقوم بوضع عدد نتائج البحث في الليبل وكذلك القيمة القصوى للبروجريس بار كود : Sub PopulateResults(matches As IEnumerable(Of Match))الإجراء Reset : نقوم باعادة كل شيء الى ما كان عليه : كود : Sub Reset()الان نأتي للاحداث : الحدث txtSearch.TextChanged : سنجري عملية البحث وايجاد النتائج اثناء الكتابة ، لهذا نستخدم الحدث txtSearch.TextChanged كود : Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChangedنقوم اولا باعادة كل شيء Reset() نعرف متغيرات للنص المطلوب البحث فيه textToSearch ونص البحث word وكذلك نتيجة البحث matches اذا كانت الكلمة ليس بها احرف ، لا نكمل التالي نقوم باجراء عمليه البحث وتخزين النتائج في matches اذا كانت النتائج خالية لا نكمل ايضا نقوم بملي الليبل وتجهيز شريط التقدم ، وكذلك ملئ الليست بوكس اذا كان خيار التلوين التلقائي معلم نقوم بتلوين النتائج حدث btnColor.Click : عند الضغط على زر التلوين نريد ان نحصل على نتائج البحث من الليست بوكس ، ثم بعد ذلك نطلب اجراء التلوين : كود : Private Sub btnColor_Click(sender As Object, e As EventArgs) Handles btnColor.Clickاذا كانت الليست فارغة او كانت النتائج فارغة هذا معناه لا يوجد نتائج لتلوينها ، لذلك نعود حدث txtSearch.GotFocus و txtSearch.LostFocus : نريد ان نعرف اذا كان مربع البحث قيد الاستخدام ام لا ، لانه في كل مرة ينفذ حدث تغير الكتابة يتم مليء الليست بوكس وينطلق حدث تغير العنصر المختار SelectedIndexChanged ويفقد مربع النص تركيزه نقوم بتعريف متغير عام textboxFocusd من نوع Boolean ، عندما تحصل الاداه على التركيز ياخذ قيمة True وعندما تفقده ياخذ قيمة False : كود : Dim textboxFocusd As Booleanالحدث lstResults.SelectedIndexChanged : عندما يختار المستخدم عنصر من الليست بوكس نريد ان نذهب الى هذا العنصر تحديدا ونقوم بتحديده في ال RichTextBox : كود : Private Sub lstResults_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstResults.SelectedIndexChangedلاحظ نختبر اذا كان مربع النص عليه تركيز لا نكمل النتيجة : [attachment=25726] ملاحظات هامة للتطوير : 1. في النصوص الطويلة تلوين الكلمات قد يأخذ وقت ملحوظ ، لذلك تعطيل التلوين التلقائي قد يكون فكرة جيدة 2. هذه الطريقة لا تأخذ بعين الاعتبار الاشكال المختلفة للحرف الواحد ، مثلا الالف : ( أاإآ ) او الواو ( وؤ ) ، ربما اقوم بتطوير شامل لهذه النقطة 3. هذه الطريقة ايضا لا تشمل حركات المصحف كالغنة وحركات الوقف وغيرها ، الموضوع للتبسيط اشتمل على الحركات الاساسية فقط 4. هذه الطريقة تعامل الحروف في المدى الحرفي Unicode من u0600 الى u06FF على انها حروف عربية ، وهي اغلبها حروف فعلا ولكن بها ايضا رموز يجب للدقة استثنائها ولكن لم ارغب ان يكون تعبير البحث معقدا لسهولة الفهم ، ربما اقوم بتطوره ليصبح اكثر دقة واخيرا : اخيرا وجب ان اقول اني اجد الموضوع على قدر كبير جدا من الاهمية ، لذلك استحق الوقت والمجهود سواء في المثال او حتى في الموضوع نفسه هنا ، اتمنى ان يكون قد قدم الافادة المطلوبة ، ويسعدني جدا ان اشرح نقطة معينة مجددا ان كنت قد قصرت فيها ، وكذلك مقترحاتكم لتطوير هذه الطريقة RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - عبد الهادي بهاب - 19-09-20 (19-09-20, 05:28 PM)Anas Mahmoud كتب : بسم الله الرحمن الرحيم اقل ما يقال .... ما شاء الله لا قوة الا بالله ... شرح جد رائع و مبذول فيه جهد واضح ...جزاكم الله خيرا ارجو ان اجد له مشروعا قريبا تطبيقيا طبعا .......انا انتر الجزء المتعلق بحركات التشكيل القرآنية ......من اجل مشروع القران RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - Anas Mahmoud - 20-09-20 (19-09-20, 11:52 PM)عبد الهادي بهاب كتب : اقل ما يقال .... ما شاء الله لا قوة الا بالله ... شرح جد رائع و مبذول فيه جهد واضح ...جزاكم الله خيرا بارك الله فيك اخي عبد الهادي ان شاء الله قريبا RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - السندبااد - 03-11-20 جزاك الله خيراً على هذا الشرح المميز، ونتمنى بالفعل أن تطور الفكرة كما تفضلت، فالموضوع مهم جداً للمبرمجين.
RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - kiki - 04-11-20 موضوع رائع وشرح اروع تم التقييم RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - Miloud - 23-08-21 بارك الله فيك اخي و تاجر عليه ان شاء الله . ما رايك باستثناء حروف التشكيل في عملية البحث.؟ صورة مرفقة RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - waelalmsry75 - 27-08-21 جزاك الله خيرا ونفع بك أخي [b]Anas Mahmoud[/b] هل يمكن تطبيق ما سبق على قاعدة بيانات access والبحث بجملة select da = New OleDbDataAdapter("select * from Kotob where nass like '%" & Txt.Text & "%'", con) RE: البحث عن الكلمات العربية داخل النصوص بالتشكيل ( التحريك ُ َ ً ِ ٍ ) - waelalmsry75 - 28-08-21 (27-08-21, 05:14 PM)waelalmsry75 كتب : جزاك الله خيرا ونفع بك أخي [b]Anas Mahmoud[/b] للتذكير |