regex - ماذا يعني "الكسل" و "الجشع" في سياق التعبيرات العادية؟




regex-greedy non-greedy (8)

أفضل ما يظهر على سبيل المثال. خيط. 192.168.1.1 و regex greedy \ b. + \ b قد تعتقد أن هذا سيعطيك الثمانية الأولى ولكنه في الواقع يطابق السلسلة بأكملها. لماذا ا!!! لأن. + الجشع ومطابقة الجشع يطابق كل حرف في '192.168.1.1' حتى يصل إلى نهاية السلسلة. هذا هو الشيء المهم !!! الآن يبدأ التراجع حرف واحد في كل مرة حتى يعثر على تطابق الرمز المميز الثالث (\ b).

إذا كانت السلسلة عبارة عن ملف نصي سعة 4 غيغابايت و 192.168.1.1 في البداية ، يمكنك بسهولة معرفة كيف سيؤدي هذا التراجع إلى حدوث مشكلة.

لجعل regex غير الجشع (كسول) وضع علامة استفهام بعد البحث الجشع الخاص بك على سبيل المثال *؟ ؟؟ +؟ ما يحدث الآن هو الرمز المميز 2 (+؟) العثور على تطابق ، ينتقل regex على طول حرف ثم يحاول الرمز المميز التالي (\ b) بدلاً من الرمز المميز 2 (+؟). لذلك تزحف على طول بحذر شديد.

هل يمكن لشخص أن يشرح هذين المصطلحين بطريقة مفهومة؟


الجشع يعني أن تعبيرك سوف يتطابق مع مجموعة كبيرة قدر الإمكان ، أما الكسل فيعني أنه سيطابق أصغر مجموعة ممكنة. لهذه السلسلة:

abcdefghijklmc

وهذا التعبير:

a.*c

مباراة الجشع سوف تتطابق مع السلسلة بأكملها ، وستتطابق المباراة البطيئة مع أول abc فقط.


بقدر ما أعرف ، فإن معظم محرك regex الجشع افتراضيا. إضافة علامة استفهام في نهاية المدقق سوف تمكن من مطابقة البطيئة.

كما ذكرAndre S في التعليق.

  • الجشع: استمر في البحث حتى لا تكون الحالة مرضية.
  • كسلان: توقف عن البحث عندما يتم استيفاء الشرط.

ارجع إلى المثال أدناه لمعرفة ما هو الجشع وما هو الكسل.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String args[]){
        String money = "100000000999";
        String greedyRegex = "100(0*)";
        Pattern pattern = Pattern.compile(greedyRegex);
        Matcher matcher = pattern.matcher(money);
        while(matcher.find()){
            System.out.println("I'm greeedy and I want " + matcher.group() + " dollars. This is the most I can get.");
        }

        String lazyRegex = "100(0*?)";
        pattern = Pattern.compile(lazyRegex);
        matcher = pattern.matcher(money);
        while(matcher.find()){
            System.out.println("I'm too lazy to get so much money, only " + matcher.group() + " dollars is enough for me");
        }
    }
}

النتيجه هي:

انا greeedy واريد 100000000 دولار. هذا هو أكثر ما أستطيع الحصول عليه.

أنا كسول جدا للحصول على الكثير من المال ، فقط 100 دولار يكفي بالنسبة لي


حاول فهم السلوك التالي:

    var input = "0014.2";

Regex r1 = new Regex("\\d+.{0,1}\\d+");
Regex r2 = new Regex("\\d*.{0,1}\\d*");

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // "0014.2"

input = " 0014.2";

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // " 0014"

input = "  0014.2";

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // ""

من التعبير العادي

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

باستخدام مقياس الكسل البطيئ ، يحاول التعبير الحد الأدنى من التطابق أولاً.


"الجشع" يعني أطول سلسلة ممكنة.

"كسول" يعني تطابق أقصر سلسلة ممكنة.

على سبيل المثال ، يطابق h.+l 'hell' في 'hello' لكن the lazy h.+?l يطابق 'hel' .


سيستهلك الجشع قدر الإمكان. من http://www.regular-expressions.info/repeat.html نرى مثال محاولة مطابقة علامات HTML مع <.+> . لنفترض أن لديك ما يلي:

<em>Hello World</em>

قد تعتقد أن <.+> ( . يعني أن أي حرف غير خطي جديد و + يعني واحد أو أكثر ) سوف يتطابق فقط مع <em> و </em> ، في حين أنه سيكون في الواقع شديد الجشع ، ويذهب من أول < إلى آخر > . هذا يعني أنه سيطابق <em>Hello World</em> بدلاً من ما تريده.

جعله كسول ( <.+?> ) سيمنع هذا. عن طريق إضافة ? بعد + ، نطلب منه أن يكرر أقل عدد ممكن من المرات ، لذا فإن الأول > يأتي عبر ، هو المكان الذي نريد إيقاف المطابقة فيه.

أود أن أشجعك على تنزيل RegExr ، وهي أداة رائعة ستساعدك على استكشاف التعبيرات العادية - RegExr طوال الوقت.


+-------------------+-----------------+------------------------------+
| Greedy quantifier | Lazy quantifier |        Description           |
+-------------------+-----------------+------------------------------+
| *                 | *?              | Star Quantifier: 0 or more   |
| +                 | +?              | Plus Quantifier: 1 or more   |
| ?                 | ??              | Optional Quantifier: 0 or 1  |
| {n}               | {n}?            | Quantifier: exactly n        |
| {n,}              | {n,}?           | Quantifier: n or more        |
| {n,m}             | {n,m}?          | Quantifier: between n and m  |
+-------------------+-----------------+------------------------------+

أضف ؟ إلى كميا لجعلها غير قهرية أي كسول.

مثال:
سلسلة الاختبار:
التعبير الجشع reg : s.*o الإخراج: stackoverflo w
تعبير reg كسول : s.*?o الإخراج: stacko verflow





non-greedy