Arasındaki fark nedir .*? ve. * düzenli ifadeler?


142

Regex kullanarak iki parçaya bir dize bölmek çalışıyorum. Dize şu şekilde biçimlendirilir:

text to extract<number>

Ben kullanıyorum (.*?)<ve <(.*?)>hangi işe yarıyor ama biraz regex okuduktan sonra ?, ifadelerde neden ihtiyacım olduğunu merak etmeye başladım . Sadece bu site aracılığıyla onları bulduktan sonra böyle yaptım, bu yüzden farkın tam olarak ne olduğundan emin değilim.


Yanıtlar:


172

Açgözlü ve açgözlü olmayan niceleyiciler arasındaki farktır.

Girişi düşünün 101000000000100.

Kullanılması 1.*1, *açgözlü - o maç kadar geriye dönük izleme sonra yolun sonuna kadar maç ve olacak 1size bırakarak 1010000000001.
.*?açgözlü değildir. *hiçbir şeyle eşleşmez, ancak eşleşene kadar ekstra karakterleri eşleştirmeye çalışır 1ve sonunda eşleşir 101.

Tüm nicelik olmayan açgözlü modu vardır: .*?, .+?, .{2,6}?ve hatta .??.

Sizin durumunuzda, benzer bir desen olabilir <([^>]*)>- büyüktür işaretinden başka bir şeyle eşleşebilir (kesinlikle konuşursak, >aradaki <ve dışında sıfır veya daha fazla karakterle eşleşir >).

Bkz Nicelik Hile Sheet .


Ah büyük> işareti dışında her şeyi son hoşuma gitti!
Doug

1
Açgözlülüğün açgözlü ?olmayanlardan nasıl farklı olduğunu açıklayabilir veya bir örnek gösterebilir misiniz ???
AdrianHHH

4
Elbette. Dize için "abc", normal ifade /\w\w?\w/tam dizeyle eşleşir "abc"- çünkü ?açgözlüdür. /\w\w??\w/tembel - sadece eşleşecek "ab". Yalnızca "abc"daha sonra başarısız olursa geriye doğru izlenir ve eşleşir .
Kobi

184

Açgözlü vs açgözlü olmayan

Normalde regex'te tekrarlama açgözlüdür : mümkün olduğu kadar çok tekrarla eşleşmeye çalışırlar ve bu işe yaramazsa ve geri gitmeleri gerektiğinde, tüm desenin eşleşmesi gerçekleşene kadar bir seferde daha az tekrarla eşleşmeye çalışırlar. bulundu. Sonuç olarak, bir maç nihayet gerçekleştiğinde, açgözlü bir tekrar mümkün olduğu kadar çok tekrarla eşleşir .

?İçine bu davranışı değiştirir miktar belirleyici bir tekrarı olarak olmayan açgözlü da adlandırılan, isteksiz ( örn Java ) (ve bazen "tembel"). Buna karşılık, bu tekrarlama ilk önce mümkün olduğunca az sayıda tekrar eşleştirmeye çalışacaktır ve bu işe yaramazsa ve geri takip etmek zorunda kaldıklarında, bir kez daha bir rept ile eşleşmeye başlarlar. Sonuç olarak, bir maç nihayet gerçekleştiğinde, isteksiz bir tekrarlama mümkün olduğunca az tekrarla eşleşir .

Referanslar


Örnek 1: A'dan Z'ye

Bu iki örüntüyü karşılaştıralım: A.*Zve A.*?Z.

Aşağıdaki girdi verildiğinde:

eeeAiiZuuuuAoooZeeee

Kalıplar aşağıdaki eşleşmeleri verir:

Önce ne A.*Zişe odaklanalım . İlk eşleşti zaman A, .*açgözlü, ilk denemeden olmanın birçok olarak eşleşecek şekilde .mümkün olduğunca.

eeeAiiZuuuuAoooZeeee
   \_______________/
    A.* matched, Z can't match

Yana Z, motor geri adım attığı uymuyor ve .*sonra bir daha az eşleşmesi gerekir .:

eeeAiiZuuuuAoooZeeee
   \______________/
    A.* matched, Z still can't match

Bu birkaç kez daha olur, nihayet buna gelene kadar:

eeeAiiZuuuuAoooZeeee
   \__________/
    A.* matched, Z can now match

Şimdi Zeşleşebilir, böylece genel desen eşleşir:

eeeAiiZuuuuAoooZeeee
   \___________/
    A.*Z matched

Buna karşılık, A.*?Zilk olarak isteksiz tekrarlama .mümkün olduğunca az eşleşir ve sonra .gerektiği kadar alır. Bu, girdide neden iki eşleşme bulduğunu açıklar.

İşte bu iki modelin eşleştiğinin görsel bir temsili:

eeeAiiZuuuuAoooZeeee
   \__/r   \___/r      r = reluctant
    \____g____/        g = greedy

Örnek: Alternatif

Birçok uygulamada, yukarıdaki girişteki iki eşleşme istenen şeydir, bu nedenle aşırı eşleşmeyi önlemek .*?için açgözlü yerine bir isteksiz kullanılır .*. Bununla birlikte, bu özel model için, ihmal edilmiş karakter sınıfı kullanan daha iyi bir alternatif vardır.

Örüntü A[^Z]*Zayrıca A.*?Zyukarıdaki girdinin örüntüsü ile aynı iki eşleşmeyi bulur ( ideone.com'da görüldüğü gibi ). reddedilen karakter sınıfı[^Z] olarak adlandırılan şeydir : başka bir şeyle eşleşmez .Z

İki desen arasındaki temel fark performanstır: daha katı olmak gerekirse, reddedilen karakter sınıfı belirli bir girdi için yalnızca bir yolla eşleşebilir. Bu desen için açgözlü veya isteksiz değiştirici kullanmanız önemli değildir. Aslında, bazı tatlarda, daha da iyi yapabilir ve hiç geri takip etmeyen iyelik nicelleştirici denilen şeyi kullanabilirsiniz.

Referanslar


Örnek 2: A'dan ZZ'ye

Bu örnek açıklayıcı olmalıdır: açgözlü, isteksiz ve reddedilmiş karakter sınıfı kalıplarının aynı girdi göz önüne alındığında nasıl farklı eşleştiğini gösterir.

eeAiiZooAuuZZeeeZZfff

Bunlar yukarıdaki girdinin eşleşmeleri:

Eşleştiklerinin görsel bir temsili:

         ___n
        /   \              n = negated character class
eeAiiZooAuuZZeeeZZfff      r = reluctant
  \_________/r   /         g = greedy
   \____________/g

İlgili konular

Bunlar, ilgi çekici olabilecek bazı konuları kapsayan yığın akışı hakkında soru ve cevaplara bağlantılardır.

Açgözlü bir tekrar diğerini geçebilir


1
İdeone.com değil rubular.com demek istedim. Diğerlerine: bu yayını benim için gözden geçirme, diğer örneklerle birlikte bir sonraki revizyonda kendim yapacağım. Ben de dahil edebilirsiniz yorumlarda geribildirim, öneri, vb vermek için çekinmeyin.
poligenelubricants


4
Bu yanıt, Yığın Taşması Düzenli İfade SSS'ye , "Niceleyiciler> Farklılıklar hakkında daha fazla bilgi ..." altında eklendi
aliteralmind

Bu cevap gerçekten seçilen cevap olmayı hak ediyor !. Ayrıntılı açıklamanız için çok teşekkür ederim.
masky007

Açgözlü olmayan etiketi ekledim . Neden, çünkü sorunun ihtiyacı vardı, ama aynı zamanda bu harika cevaba daha fazla kullanıcıyı hunlayacağı için. Başka bir deyişle, harika bir yanıt verirseniz ve yanıt soruda olmayan bir etiket kullanırsa, OP'yi etiketin güncel olduğunu bilmediği için etiketi ekleyin.
Guy Coder

21

Diyelim ki:

<a></a>

<(.*)>eşleşir a></aolarak nerede <(.*?)>eşleşir a. İkincisi, ilk maçından sonra durur >. Bir veya 0 eşleşmesinin .*ardından bir sonraki ifadeyi denetler .

İlk ifade <(.*)>, ilk ifadeyle eşleşirken durmaz >. Son maçına kadar devam edecek >.


Bunu anlamak, yukarıdaki açıklamadan daha kolaydır.
Prometheus
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.