سؤال

أدلي يحصل على ملف نص عادي وتدريج يولد "العلامات" بواسطة استبدال الشروط من النص في العلامات. بسبب وجود بعض المصطلحات المركبة ، الطريق الوحيد (أعتقد) هو استخدام replaceall Regex.

بفضل Friends of Stackoverflow ، في سؤالي الأخير ، حصلت على regex ممتازة لتطبيقي ، ولكن بعد الاختبارات ، ظهرت حاجة جديدة:

"regex لاستبدال كل الكلمات خارج علامة وخارج كلمة أخرى"

الكود الأريدي:

String str = "world worldwide <a href=\"world\">my world</world>underworld world";
str = str.replaceAll("\\bworld\\b(?![^<>]*+>)", "repl");
System.out.println(str);

أحتاج الآن استبدال "العالم" فقط (خارج علامة Ofcourse) و ليس "العالم السفلي" أو "العالم"

نتيجة متوقعة:

repl worldwide <a href="world">my world</world>underworld repl
هل كانت مفيدة؟

المحلول

لا أعتقد أن Regex هي أفضل أداة لهذا الوظيفة ، ولكن إذا كنت تريد فقط تعديل وتحسين ما لديك الآن ، يمكنك استخدام Word Boundary \b, ، قم بإلقاء مجموعة التقاط غير الضرورية ومواصفات التكرار الاختيارية ، واستخدم التكرار التملك:

\bworld\b(?![^<>]*+>)

ال \bworld\b سيضمن ذلك "world" تحيط بها مراسي الحدود كلمة الصفر. هذا سيمنعه من مطابقة "world" في "underworld" و "worldwide". لاحظ أن تعريف حدود الكلمة قد لا يكون بالضبط ما تريده ، على سبيل المثال \bworld\b لن يتطابق مع "world" في "a_world_domination".

يحتوي النمط الأصلي أيضًا على مجموعة فرعية تبدو (x+)?. ربما يتم صياغة هذا بشكل أفضل على أنه ببساطة x*. هذا هو ، بدلاً من "صفر أو واحد" ? من "واحد أو أكثر" +, ، ببساطة "صفر أو أكثر" *.

مجموعة التقاط (…) غير مطلوبة من الناحية الوظيفية ، ولا يبدو أنك بحاجة إلى التقاط أي استبدال في الاستبدال ، لذلك يمكن للتخلص منه تحسين الأداء (عندما تحتاج إلى جانب التجميع ، ولكن ليس جانب التقاط ، يمكنك استخدام غير مجموعة التقاط (?:…) في حين أن).

لاحظ أيضًا أنه بدلاً من [^<], ، نمنع الآن كلا الأقواس [^<>]. الآن يمكن تحديد التكرار على أنه تملك لأنه لا يلزم التراجع في هذه الحالة.

(ال […] هو فئة الشخصية. شيء مثل [aeiou] يطابق واحدة من أي من حروف العلة الصغيرة. [^…] هو نفي فئة الشخصية. [^aeiou] يطابق واحد من اي شي لكن حروف العلة الصغيرة.)

بالطبع (?!…) هو نفي انظر الى الامام؛ ويؤكد أن نمط معين يمكن ليس تكون مطابقة. لذا فإن النمط العام يقرأ مثل هذا:

\bworld\b(?![^<>]*+>)
\_______/\__________/ NOT the case that
 "world"                      the first bracket to its right is a closing one
 surrounded by
 word boundary anchors

مراجع


لاحظ أنه للحصول على عصر خلفي في سلسلة Java حرفية ، تحتاج إلى مضاعفة ذلك ، وبالتالي فإن النمط بأكمله كحرف Java string هو "\\bworld\\b(?![^<>]*+>)".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top