كيف يمكنني مطابقة أي حرف عبر خطوط متعددة في تعبير منتظم؟

StackOverflow https://stackoverflow.com/questions/159118

  •  03-07-2019
  •  | 
  •  

سؤال

على سبيل المثال ، هذا regex

(.*)<FooBar>

سيطابق:

abcde<FooBar>

ولكن كيف يمكنني الحصول عليها لتتناسب مع خطوط متعددة؟

abcde
fghij<FooBar>
هل كانت مفيدة؟

المحلول

يعتمد ذلك على اللغة ، ولكن يجب أن يكون هناك معدل يمكنك إضافته إلى نمط Regex. في PHP هو:

/(.*)<FooBar>/s

ال س في النهاية يتسبب في مطابقة النقطة الكل شخصيات بما في ذلك الخطوط الجديدة.

نصائح أخرى

جرب هذا:

((.|\n)*)<FooBar>

تقول بشكل أساسي "أي حرف أو سطر جديد" متكرر صفر أو أكثر.

إذا كنت تستخدم Eclipse Search ، فيمكنك تمكين خيار "dotall" لجعل "." تطابق أي حرف بما في ذلك محددات الخط: فقط أضف "(؟ s)" في بداية سلسلة البحث الخاصة بك. مثال:

(?s).*<FooBar>

السؤال هو ، يمكن . نمط المباراة أي حرف؟ الجواب يختلف من محرك إلى محرك. الفرق الرئيسي هو ما إذا كان يتم استخدام النمط بواسطة مكتبة POSIX أو Non-Posix Regex.

ملاحظة خاصة حول : لا تعتبر تعبيرات منتظمة ، ولكن . يطابق أي char هناك ، مثل محركات Posix القائمة.

ملاحظة أخرى على و : ال . يطابق أي char افتراضيًا (العرض التوضيحي): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); (tokens تحتوي على أ abcde\n fghij العنصر).

أيضا ، في كل من 's regex القواعد النقطية تتطابق خط الكسر بشكل افتراضي. تتيح لك Boost's Ecmascript Grammar إيقاف هذا الأمر regex_constants::no_mod_m (مصدر).

أما بالنسبة لل (إنه يعتمد على Posix) ، والاستخدام n اختيار (العرض التوضيحي): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

المحركات القائمة على Posix:

مجرد . تطابق بالفعل فترات استراحة الخط ، لا حاجة لاستخدام أي معدلات ، انظر (العرض التوضيحي).

ال (العرض التوضيحي), (العرض التوضيحي), (TRE ، Base R Default Engine بدون perl=TRUE, ، لقاعدة R مع perl=TRUE أو ل سلسلة/سلسلة الأنماط ، استخدم (?s) المعدل المضمن) (العرض التوضيحي) علاج أيضا . نفس الطريقة.

لكن, ، معظم الأدوات القائمة على POSIX معالجة خط الإدخال سطر. بالتالي، . لا يتطابق مع انهار الخط لمجرد أنها ليست في نطاق. فيما يلي بعض الأمثلة حول كيفية تجاوز هذا:

  • - هناك حلول متعددة ، والأكثر دقة ولكن ليست آمنة للغاية sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' (H;1h;$!d;x; تملق الملف في الذاكرة). إذا كان يجب تضمين الخطوط الكاملة ، sed '/start_pattern/,/end_pattern/d' file (ستنتهي الإزالة من البداية مع خطوط متطابقة) أو sed '/start_pattern/,/end_pattern/{{//!d;};}' file (مع استبعاد خطوط المطابقة) يمكن النظر فيها.
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str" (-0 تطفو الملف بأكمله في الذاكرة ، -p يطبع الملف بعد تطبيق البرنامج النصي المقدم -e). لاحظ ذلك باستخدام -000pe سيقوم بتشويش الملف وتنشيط "وضع الفقرة" حيث يستخدم Perl الخطوط الجديدة المتتالية (\n\n) كما فاصل السجل.
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file. هنا، z يمكّن الملف ، (?s) يتيح وضع dotall ل . نمط، (?i) يمكّن الوضع غير الحساس للحالة ، \K يحذف النص المتطابق حتى الآن ، *? هو كميات كسول ، (?=<Foobar>) يطابق الموقع من قبل <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file (M تمكين الملف الضوضاء هنا). ملحوظة pcregrep هو حل جيد لنظام التشغيل Mac OS grep المستخدمون.

انظر العروض التوضيحية.

المحركات غير القائمة على بوسيكس:

الملاحظات على (?s):

في معظم محركات غير بوسيكس ، (?s) يمكن استخدام المعدل المضمون (أو خيار العلم المدمج) لفرضه . لمطابقة استراحات الخط.

إذا وضعت في بداية النمط ، (?s) يغير البهورة للجميع . في النمط. إذا (?s) يتم وضعه في مكان ما بعد البداية ، فقط هؤلاء . سوف تتأثر التي تقع على يمينها ما لم هذا نمط تم تمريره إلى بيثون re. في بيثون re, ، بغض النظر عن (?s) الموقع ، النمط كله . تتأثر. ال (?s) توقف التأثير باستخدام (?-s). يمكن استخدام مجموعة معدلة للتأثير فقط على نطاق محدد لنمط regex (على سبيل المثال Delim1(?s:.*?)\nDelim2.* سيجعل الأول .*? تطابق عبر الخطوط الجديدة والثانية .* سوف تطابق فقط بقية الخط).

ملاحظة Posix:

في المحركات غير المرسب ، لمطابقة أي شار ، [\s\S] / [\d\D] / [\w\W] يمكن استخدام البنيات.

في Posix ، [\s\S] لا يتطابق مع أي char (كما هو الحال في JavaScript أو أي محرك غير posix) لأن تسلسل regex Escape لا يتم دعمه داخل تعبيرات قوسين. [\s\S] يتم تحليلها كتعبيرات بين قوسين تتطابق مع شار واحد ، \ أو s أو S.

في JavaScript ، استخدم /[\S\s]*<Foobar>/. مصدر

([\s\S]*)<FooBar>

تتطابق النقطة جميعها باستثناء الخطوط الجديدة ( r n). لذا استخدم s s ، والتي ستتطابق مع جميع الأحرف.

في روبي يمكنك استخدام ال 'mالخيار (متعدد الأسلحة):

/YOUR_REGEXP/m

نرى وثائق regexp على Ruby-doc.org لمزيد من المعلومات.

يمكننا أيضا استخدام

(.*?\n)*?

لمطابقة كل شيء بما في ذلك الخط الجديد بدون جشع

هذا سيجعل الخط الجديد اختياريًا

(.*?|\n)*?

"." عادة لا تتطابق مع كسر الخط. تتيح لك معظم محركات Regex إضافة ملف S-Flag (تسمى أيضًا DOTALL و SINGLELINE) ليصنع "." تطابق أيضا الخطوط الجديدة. إذا فشل ذلك ، يمكنك أن تفعل شيئًا مثل [\S\s].

لل Eclipse عملت بعد التعبير:

فو

بار Jadajada "

تعبير عادي:

Foo[\S\s]{1,10}.*Bar*
/(.*)<FooBar>/s

يتسبب S في النقطة (.) لمطابقة عوائد النقل

في التعبير العادي القائم على Java يمكنك استخدامه [\s\S]

لاحظ أن (.|\n)* يمكن أن تكون أقل كفاءة من (على سبيل المثال) [\s\S]* (إذا كانت regexes لغتك تدعم مثل هذه الهروب) وإلى العثور على كيفية تحديد المعدل الذي يجعل. تطابق أيضا الخطوط الجديدة. أو يمكنك الذهاب مع بدائل posixy مثل [[:space:][:^space:]]*.

استخدم regexoptions.singleline ، فهو يغير معنى. لتشمل الخطوط الجديدة

regex.replace (المحتوى ، SearchText ، replacetext ، regexoptions.singleline) ؛

المحلول:

استخدم Modifier Modifier SU الحصول على المطابقة المطلوبة في PHP.

مثال:

preg_match('/(.*)/sU',$content,$match);

مصدر:

http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modiers.php

في سياق الاستخدام داخل اللغات ، تعمل التعبيرات العادية على الأوتار ، وليس الخطوط. لذلك يجب أن تكون قادرًا على استخدام Regex بشكل طبيعي ، على افتراض أن سلسلة الإدخال لها خطوط متعددة.

في هذه الحالة ، ستطابق Regex المعطى السلسلة بأكملها ، منذ ""u003CFooBar> "يوجد السيطرة على ما إذا كان "". "سوف يتطابق مع الخط الجديد ، مما يمنحك الاختيار.

استخدام التعبير العادي القائم على الخط هو عادة لأشياء خط الأوامر مثل Egrep.

واجهت نفس المشكلة وحلها ربما ليس أفضل طريقة ولكنها تعمل. لقد استبدلت كل فترات استراحة الخط قبل أن أقوم بمطابقتي الحقيقية:

mystring= Regex.Replace(mystring, "\r\n", "")

أنا أتعامل مع HTML ، لذا فإن استراحات الخط لا تهمني حقًا في هذه الحالة.

لقد جربت كل الاقتراحات أعلاه بدون حظ ، أنا أستخدم .NET 3.5 FYI

في JavaScript ، يمكنك استخدام [^]* للبحث عن صفر لأحرف لا حصر لها ، بما في ذلك فواصل الخط.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>

عموما . لا يتطابق مع الخطوط الجديدة ، لذا حاول ((.|\n)*)<foobar>

أردت أن أتطابق مع مجموعة خاصة إذا كانت كتلة في جافا

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

إذا استخدمت regexp

if \(isTrue(.|\n)*}

وشملت الدعامة الإغلاق لكتلة الطريقة لذلك استخدمت

if \(!isTrue([^}.]|\n)*}

لاستبعاد الدعامة الختامية من مباراة Wildcard.

غالبًا ما يتعين علينا تعديل فرعية مع بعض الكلمات الرئيسية المنتشرة عبر الخطوط التي تسبق السلسلة الفرعية. النظر في عنصر XML:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

لنفترض أننا نريد تعديل 81 ، لبعض القيمة الأخرى ، قل 40. حدد أولاً .UID.21..UID., ثم تخطي جميع الشخصيات بما في ذلك \n حتى .PercentCompleted.. نمط التعبير العادي ومواصفات الاستبدال هي:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

المجموعة الفرعية (.|\n) ربما المجموعة المفقودة $3. إذا نجحنا في عدم التغلب عليها (?:.|\n) ثم $3 هو (<PercentComplete>). لذلك النمط و replaceSpec يمكن أن يكون أيضًا:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

ويعمل الاستبدال بشكل صحيح كما كان من قبل.

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