arasındaki fark nedir ?:, ?! ve? = normal ifadede?


107

Bu ifadelerin anlamını aradım ama aralarındaki tam farkı anlayamadım. Dedikleri bu:

  • ?: İfadeyi eşleştirin ama yakalamayın.
  • ?= Bir soneki eşleştirin ancak onu yakalama dışında bırakın.
  • ?! Sonek yoksa eşleştirin.

Bunları basit RegEx'te kullanmayı denedim ve herkes için benzer sonuçlar aldım. örnek: aşağıdaki 3 ifade çok benzer sonuçlar verir.

  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?!\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?=\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9]+)*

Lütfen bize test durumunuzu gösterin. Aynı sonuçları vermemelidirler.
Bergi

@ sepp2k, birkaç durumda aynı sonuçlara benzer, bunlardan biri soruda belirtilmiştir.
RK Poddar

@Bergi, ingilizce kelimeler, telefon numaraları, url'ler, e-posta adresleri, numaralar vb. İçeren rastgele verilerle test ettim.
RK Poddar

4
@RKAgarwal Ah, orada ne yaptığını görüyorum. *Grupların arkasına bir eklediniz , bu yüzden yok sayılırlar.
sepp2k

noobie not : bunları yalnızca parantezin başında kullanırsınız ve parantez bir yakalama grubu oluşturur (farklı parantez kümeleri metnin farklı bölümlerini çıkarır).
Ryan Taylor

Yanıtlar:


155

Arasındaki fark ?=ve ?!eski maç için verilen ifade gerektirir ve ikinci bu için gerektirmesidir değil aynı. Örneğin a(?=b), "ab" deki "a" ile eşleşecek, "ac" deki "a" ile eşleşmeyecektir. Oysa a(?!b)"ac" deki "a" ile eşleşecek, "ab" deki "a" ile eşleşmeyecektir.

Arasındaki fark ?:ve ?=olmasıdır ?=ederken dışlayan bütün maç den ifadesi ?:sadece bir yakalama grubunu oluşturmaz. Örneğin a(?:b), "abc" deki "ab" ile eşleşirken, a(?=b)yalnızca "abc" deki "a" ile eşleşir. a(b)"abc" in "ab" eşleşir ve "b" içeren bir yakalama oluşturun.


81
?:  is for non capturing group
?=  is for positive look ahead
?!  is for negative look ahead
?<= is for positive look behind
?<! is for negative look behind

Normal ifadelerde önden okuma ile ilgili çok iyi eğitim ve örnekler için lütfen buraya bakın: http://www.regular-expressions.info/lookaround.html .


15
Yine de JavaScript geriye bakmayı bilmiyor.
Bergi

1
Bu, genel normal ifade için daha eksiksizdir.
Yan Yang

/ (? <= ^ a) b / benim için javascript'te çalıştı! İnternette Javascript'te geriye bakmak için bir eğitim yok gibi görünüyor.
Y. Yoshii

Yalnızca tarayıcıların son sürümleri JS'de arkaya bakmayı desteklemeye başladı
anubhava

- anubhava Saf düzenli ifadeyi kullanarak / (? <= ^ A) b / için herhangi bir alternatif bilmiyorum. Belki yapabilirim ama geri arama işlevlerine güvenmem gerekir.
Y. Yoshii

21

Daha iyi anlamak için üç ifadeyi artı bir yakalama grubunu uygulayalım ve her davranışı analiz edelim.

  • () yakalama grubu - parantez içindeki normal ifade eşleşmeli ve eşleşme bir yakalama grubu oluşturmalıdır
  • (?:) yakalamayan grup - parantez içindeki normal ifade eşleşmelidir ancak yakalama grubunu oluşturmaz
  • (?=) olumlu ileriye bak - normal ifadenin eşleşmesi gerektiğini iddia eder
  • (?!) negatif ileriye bak - normal ifadeyle eşleştirmenin imkansız olduğunu iddia eder

En uygulayalım q(u)iiçin çıkın . q ile qeşleşir ve yakalama grubu u ile eşleşir . Yakalama grubu içindeki maç alınır ve bir yakalama grubu oluşturulur. Böylece motor devam ediyor . Ve i eşleşecek . Bu son maç denemesi başarılı. qui eşleştirilir ve u ile bir yakalama grubu oluşturulur.uii

En uygulayalım q(?:u)iiçin çıkın . Yine q ile qeşleşir ve yakalamayan grup u ile eşleşir . Yakalamayan gruptan maç alınır, ancak yakalama grubu oluşturulmaz. Böylece motor devam ediyor . Ve i eşleşecek . Bu son maç denemesi başarılı. qui eşleştiuii

En uygulayalım q(?=u)iiçin çıkın . Önden bakış olumludur ve bunu başka bir belirteç izler. Yine, qmaçları q ve umaçları u . Yine, önden gelen eşleşme atılmalıdır, böylece motor idizeden u'ya geri döner . Önden bakış başarılı oldu, bu yüzden motor devam ediyor i. Ama ui eşleşemez . Yani bu maç girişimi başarısız olur.

En uygulayalım q(?=u)uiçin çıkın . Önden bakış olumludur ve bunu başka bir belirteç izler. Yine, qmaçları q ve umaçları u . Önden gelen eşleşme atılmalıdır, böylece motor udizeden u'ya geri adım atar . Önden bakış başarılı oldu, bu nedenle motor devam ediyor u. Ve umaç olacak u . Yani bu maç girişimi başarılı. qu eşleşti

En uygulayalım q(?!i)uiçin çıkın . Bu durumda bile ilerleme pozitiftir (çünkü ieşleşmez) ve ardından başka bir belirteç gelir. Yine q ile qeşleşir ve u ile eşleşmez . Önden gelen eşleşme atılmalıdır, böylece motor dizeden u'ya geri adım atar . Önden bakış başarılı oldu, bu nedenle motor devam ediyor . Ve maç olacak u . Yani bu maç girişimi başarılı. qu eşleştiiuuu

Dolayısıyla, sonuç olarak, önden bakan ve yakalamayan gruplar arasındaki gerçek fark, sadece varlığını test etmek veya test etmek ve maçı kaydetmek isteyip istemediğinizle ilgilidir. Grup yakalama pahalıdır, bu yüzden dikkatli kullanın.


> böylece motor dizedeki i'den u'ya geri döner. Önden okuma başarılı oldu, bu nedenle motor i ile devam ediyor. Ama seninle eşleşemem BU tamamen kafa karıştırıcı. Bu ileriye dönükse neden geri adım atalım ?
Yeşil

1
@Green Önden okuma ve diğer etrafa bakma yapıları hakkında anlaşılması gereken önemli bir şey, alt ifadelerinin eşleşip eşleşmediğini görmek için hareketlerden geçmelerine rağmen, aslında herhangi bir metni "tüketmezler". Bu biraz kafa karıştırıcı olabilir
freedev

7

Şunlarla eşleştirmeyi deneyin foobar:

/foo(?=b)(.*)/
/foo(?!b)(.*)/

İlk normal ifade eşleşecek ve ilk alt eşleşme olarak "bar" değerini döndürecektir - (?=b) eşleşme "b" ile eşleşir, ancak onu tüketmez, onu aşağıdaki parantezler için bırakır.

İkinci normal ifade eşleşmeyecektir çünkü "foo" nun ardından "b" den farklı bir ifade gelmesini bekler.

(?:...)(...)Simple ile tamamen aynı etkiye sahiptir , ancak bu kısmı bir alt eşleşme olarak döndürmez.


0

İddiaları anlamanın en basit yolu, onları normal ifadeye eklenen komut olarak ele almaktır. Motor bir iddia için çalıştığında, iddia tarafından açıklanan durumu derhal kontrol edecektir. Sonuç doğruysa, normal ifadeyi çalıştırmaya devam edin.


0

Gerçek fark bu:

>>> re.match('a(?=b)bc', 'abc')
<Match...>
>>> re.match('a(?:b)c', 'abc')
<Match...>

# note:
>>> re.match('a(?=b)c', 'abc')
None

"?:" Veya "? =", "?:" Ve "? =" Sonrasındaki içeriği umursamıyorsanız, aynıdır. Her ikisi de kullanılabilir.

Ancak, daha fazla işlem için bu içeriğe ihtiyacınız varsa (yalnızca her şeyi eşleştirmek değil. Bu durumda, "a (b)" yi kullanabilirsiniz), bunun yerine "? =" Kullanmanız gerekir. Neden "?:" Hemen geçecek.

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.