Düzenli ifadeler bağlamında 'tembel' ve 'açgözlü' ne anlama geliyor?


Yanıtlar:


644

Açgözlü mümkün olduğunca tüketecektir. Gönderen http://www.regular-expressions.info/repeat.html biz HTML etiketlerini maç için çalışmakla örneğe bakın <.+>. Aşağıdakilere sahip olduğunuzu varsayalım:

<em>Hello World</em>

Bunu düşünebilir <.+>( .vasıta olmayan herhangi satır karakteri ve +araçlar bir ya da daha ) sadece eşleşir <em>ve </em>gerçekte çok hırslı olacak zaman, ve ilk gitmek <son için >. Bu, <em>Hello World</em>istediğin yerine eşleşeceği anlamına gelir .

Tembel ( <.+?>) yapmak bunu engelleyecektir. Ekleyerek ?sonra +, biz tekrar söylemek mümkün olduğunca az zamanları gibi ilk böylece >biz eşleştirme durdurmak istediğimiz yere rastlar vardır.

Düzenli İfadeleri keşfetmenize yardımcı olacak harika bir araç olan RegExr'i indirmenizi öneririm - her zaman kullanıyorum.


2
yani açgözlü kullanırsanız 3 (1 eleman + 2 etiket) veya sadece 1 maç (1 eleman) olur mu?
ajsie

10
İlk başlayarak, sadece 1 kez eşleşir < son ile biten > .
Sampson

3
Ancak tembel hale getirmek, aradaki metni göz ardı ederek (ifadeye uymadığından) bize hem açılış hem de kapanış etiketi vererek iki kez eşleşir.
Sampson

Her zaman kullandığım başka bir harika araç: debuggex.com Ayrıca bir "StackOverflow Embed" işlevi vardır.
Ron van der Heijden

8
Sadece bu konuda gitmek için açgözlü bir yol olduğunu eklemek için: <[^>]+> regex101.com/r/lW0cY6/1
alanbuchanan

302

'Açgözlü' , mümkün olan en uzun dizeyle eşleşmek anlamına gelir.

'Tembel' mümkün olan en kısa karakter dizisiyle eşleşir.

Örneğin, açgözlü h.+lmaçlar 'hell'içinde 'hello'ama tembel h.+?lmaçlar 'hel'.


97
Parlak, bu kadar tembel l koşulu tatmin olur olmaz duracak, ama açgözlü sadece l koşulu tatmin edilmediğinde duracağı anlamına mı geliyor?
Andrew S

3
Gönderiyi okuyan tüm insanlar için: açgözlü veya tembel niceleyiciler kendi başlarına mümkün olan en uzun / en kısa dize ile uyuşmayacaktır. Ya bir kullanması gerekir temperli açgözlü jetonu veya olmayan regex yaklaşımları kullanırlar.
Wiktor Stribiżew

3
@AndrewS Örnekteki çift ll tarafından karıştırılmamalıdır. Açgözlü mümkün olan en kısa alt dize ile eşleşir, açgözlü mümkün olan en uzun alt dize ile eşleşir. Açgözlü h.+lmaçlar 'helol'içinde 'helolo'ama tembel h.+?lmaçlar 'hel'.
v.shashenko

3
@FloatingRock: Hayır , isteğe bağlı ancak farklı bir sözdizimi x?anlamına gelir . Eşleşen bir şey bulduktan sonra durmak anlamına gelir - tembel eşleme. x+?
slebetman

1
@FloatingRock: Farklı sözdizimini nasıl farklılaştırdığınıza gelince, basit: ?isteğe bağlı ve +?tembel anlamına gelir. Bu nedenle \+?araçlar +isteğe bağlıdır.
slebetman

113
+-------------------+-----------------+------------------------------+
| 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  |
+-------------------+-----------------+------------------------------+

Ekle ? tembel hale getirmek için bir niceleyiciye.

Örnek:
test dizesi: stackoverflow
açgözlü reg ifade : s.*ooutput: stackoverflo w
tembel reg ifade : s.*?ooutput: stacko verflow


2
değil ?? eşittir ? . Benzer şekilde, {n} değil mi? {n} ile eşdeğer
Sayı 945

5
@BreakingBenjamin: hayır ?? , 0 veya 1 oluşumunu döndürme seçeneği olduğunda, 0 (tembel) alternatifini seçer. Farkı görmek için karşılaştırmak re.match('(f)?(.*)', 'food').groups()için re.match('(f)??(.*)', 'food').groups(). İkincisi, (f)??olsa bile önde gelen 'f' ile eşleşmeyecek. Dolayısıyla 'f' ikinci '. *' Yakalama grubu tarafından eşleştirilecektir. Eminim '{n}?' İle bir örnek oluşturabilirsiniz? çok. Kuşkusuz bu ikisi çok nadiren kullanılır.
smci

55

Açgözlü, ifadenizin mümkün olduğunca büyük bir grupla eşleşeceği anlamına gelir, tembel anlamına gelir, mümkün olan en küçük grupla eşleşir. Bu dize için:

abcdefghijklmc

ve bu ifade:

a.*c

Açgözlü bir maç tüm dizeyle eşleşecek ve tembel bir maç sadece ilkiyle eşleşecek abc.


16

Bildiğim kadarıyla, çoğu regex motoru varsayılan olarak açgözlü. Sayısallaştırıcının sonuna bir soru işareti eklemek tembel eşleşmeyi etkinleştirir.

@Andre S'nin yorumda belirtildiği gibi.

  • Açgözlü: Koşul sağlanana kadar aramaya devam edin.
  • Tembel: Koşul sağlandığında aramayı durdurun.

Açgözlü ve tembel olanlar için aşağıdaki örneğe bakın.

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");
        }
    }
}


Sonuç:

I'm greeedy and I want 100000000 dollars. This is the most I can get.

I'm too lazy to get so much money, only 100 dollars is enough for me

9

Alınan www.regular-expressions.info

Açgözlülük : Açgözlü niceleyiciler önce jetonu mümkün olduğunca çok kez tekrarlamaya çalışır ve genel bir maç bulmak için motor geri tepme olarak yavaş yavaş eşleşmeleri bırakır .

Tembellik : Tembel nicelik belirteci ilk önce belirteci gerektiği kadar tekrar eder ve genel bir eşleşme bulmak için motor normal ifadeden geri çekildikçe maçı yavaş yavaş genişletir.


6

Gönderen Düzenli İfade

Düzenli ifadelerdeki standart niceleyiciler açgözlüdür, yani olabildiğince çok eşleşirler, sadece normal ifadenin geri kalanıyla eşleşmek için gerektiği kadar geri verirler.

Tembel bir nicelik belirteci kullanarak, ifade önce en düşük eşleşmeyi dener.


4

Açgözlü eşleme. Normal ifadelerin varsayılan davranışı açgözlü olmaktır. Bu, daha küçük bir parça sözdizimsel olarak yeterli olsa bile, bir desene uyuncaya kadar mümkün olduğunca çıkarmaya çalıştığı anlamına gelir.

Misal:

import re
text = "<body>Regex Greedy Matching Example </body>"
re.findall('<.*>', text)
#> ['<body>Regex Greedy Matching Example </body>']

İlk '>' oluşumuna kadar eşleştirmek yerine, tüm dizgeyi çıkardı. Bu, regex'in varsayılan açgözlü veya 'hepsini al' davranışıdır.

Tembel eşleme ise 'mümkün olduğunca az zaman alıyor'. Bu ?, desenin sonuna a eklenerek gerçekleştirilebilir .

Misal:

re.findall('<.*?>', text)
#> ['<body>', '</body>']

Yalnızca ilk eşleşmenin alınmasını istiyorsanız, bunun yerine arama yöntemini kullanın.

re.search('<.*?>', text).group()
#> '<body>'

Kaynak: Python Normal İfade Örnekleri


3

Açgözlü, hiçbiri kalmayıncaya kadar deseninizi tüketeceği ve daha fazla bakamayacağı anlamına gelir.

Tembel, istediğiniz ilk desenle karşılaşır karşılaşmaz duracaktır.

Sık karşılaştığım yaygın bir örnek \s*-\s*?normal ifadedir([0-9]{2}\s*-\s*?[0-9]{7})

Birincisi \s*, sayılarla *karşılaşıldıktan sonra mümkün olduğunca çok beyaz boşluk arayacak ve sonra bir çizgi karakteri "-" arayacak şekilde açgözlü olarak sınıflandırılmıştır . İkincisi \s*?tembel olduğu için şimdiki zamandan dolayı *?, ilk beyaz boşluk karakterine bakacak ve orada duracak demektir.


3

En iyi örnek olarak gösterilmiştir. Dize. 192.168.1.1ve açgözlü bir regex \b.+\b Bunun size 1'inci sekizlisini vereceğini düşünebilirsiniz, ancak aslında tüm dizeyle eşleşir. Neden? Çünkü. + Açgözlüdür ve açgözlü bir eşleşme 192.168.1.1dizenin sonuna ulaşana kadar her karakteri eşleştirir . Önemli olan bu! Şimdi, 3. belirteç ( \b) için bir eşleşme bulana kadar bir kerede bir karakter geri izlemeye başlar .

4GB metin dosyası ve 192.168.1.1 dizesi başlangıçtaysa, bu geri izlemenin nasıl bir soruna neden olacağını kolayca görebilirsiniz.

Normal olmayan açgözlü (tembel) yapmak için açgözlü aramanızdan sonra bir soru işareti koyun.

*?
??
+?

Şimdi olan şey, jeton 2 ( +?) bir eşleşme bulur, normal ifade bir karakter boyunca hareket eder ve ardından \bjeton 2 ( +?) yerine bir sonraki jetonu ( ) dener . Böylece zekice sürünüyor.


0

Açgözlü Nicelleştiriciler IRS / ATO gibidir: mümkün olduğunca çok şey alırlar:

Eğer oradaysa, gelip alırlar. Hepsini alacaklar:

Örneğin, IRS bu normal ifadeyle eşleşir: .*

$50,000 - IRS hepsini alacak. Bu açgözlü .*{4}?ers

Bir örnek için buraya bakın: regexr.com/4t27f

Açgözlü olmayan niceleyiciler - mümkün olduğunca az alırlar

Öte yandan, vergi iadesi talep edersem, IRS ani açgözlü olmaz ve bu nicelik belirtecini kullanırlar:

(.{2}?)([0-9]*)Bu ifadeye karşı: $50,000İlk grup ihtiyacı olmayan ve sadece eşleşir $5- bu yüzden $5geri ödeme alırım . Geri kalanı Sam amca tarafından boşa harcanmak üzere alınır.

Buraya bakınız: Açgözlü olmayan örnek .

Neden rahatsız oluyorsun?

Bir ifadenin belirli bölümlerini eşleştirmeye çalışıyorsanız önemli hale gelir. Bazen her şeyi eşleştirmek istemezsiniz.


-3

aşağıdaki davranışı anlamaya çalışın:

    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); // ""
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.