Python açgözlü olmayan normal ifadeler


150

Python eşleşmeleri yerine "(.*)"böyle bir python regex'i nasıl yapabilirim ?"a (b) c (d) e""b""b) c (d"

Bunun "[^)]"yerine kullanabileceğimi biliyorum ".", ama normal ifademi biraz daha temiz tutan daha genel bir çözüm arıyorum. Python'a "hey, bunu mümkün olan en kısa sürede eşleştir" demenin bir yolu var mı?

Yanıtlar:


209

Tamamen güçlü olanı *?

Dokümanlardan Açgözlü ve Açgözlü Olmayan

olmayan açgözlü eleme *?, +?, ??, veya {m,n}?[...] olarak maç biraz olabildiğince metin.


İnternet Arşivi'ne göre, tüm bu bağlantı Python "re" modülü belgelerinin bir kopyasıydı, bu yüzden Trey'in bağlantısı da işe yarıyor.
spiffytech

2
bunun için ortak ingilizce adı *?nedir?
Trevor Boyd Smith

Wildbell Karakterleri @Trevor Boyd Smith
Serge

3
Buna "açgözlü olmayan" niteleyici denir
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Dokümanlara göre :

' *', ' +' Ve ' ?' niteleyicilerin hepsi açgözlüdür; mümkün olduğunca çok metin eşleşir. Bazen bu davranış istenmez; RE <.*>' <H1>title</H1>' ile eşleştirilirse , sadece ' <H1>' ile değil tüm dizeyle eşleşir . Niteleyiciden ?sonra ' ' eklemek maçı açgözlü veya minimal bir şekilde gerçekleştirir; mümkün olduğunca az karakter eşleştirilir. .*?Önceki ifadede kullanmak yalnızca ' <H1>' ile eşleşecektir .


14

Çalışmaz mıydı \\(.*?\\)? Bu açgözlü olmayan sözdizimidir.


5

Diğerlerinin söylediği gibi? * niceleyicideki değiştirici derhal sorununuzu çözecektir, ancak dikkatli olun, regex'lerin çalışmayı bıraktığı alanlara sapmaya başlıyorsunuz ve bunun yerine bir ayrıştırıcıya ihtiyacınız var. Örneğin, "(foo (bar)) baz" dizesi sorunlara neden olur.


5

Kanunsuz bir eşleşme kullanmak iyi bir başlangıçtır, ancak herhangi bir kullanımını yeniden düşünmenizi de öneririm .*- bu ne olacak?

groups = re.search(r"\([^)]*\)", x)

3

"(B)" ile eşleşmesini ister misiniz? Zitrax ve Paolo'nun önerdiği gibi yapın. "B" ile eşleşmesini ister misiniz? Yapmak

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Başlamak için normal ifadelerde "*" kullanılmasını önermiyorum. Evet, biliyorum, en çok kullanılan çok karakterli sınırlayıcı, ancak yine de kötü bir fikir. Bunun nedeni, o karakter için herhangi bir tekrarlama miktarıyla eşleşmesine rağmen, "any" ifadesinin 0 içermesidir; bu genellikle kabul etmemek için bir sözdizimi hatası atmak istediğiniz bir şeydir. Bunun yerine, +uzunluk> 1'in herhangi bir tekrarıyla eşleşen işareti kullanmanızı öneririm . Dahası, görebildiğim kadarıyla, sabit uzunlukta parantezli ifadelerle uğraşıyorsunuz. Sonuç olarak, {x, y}sözdizimini muhtemelen istenen uzunluğu belirtmek için kullanabilirsiniz .

Ancak, gerçekten açgözlü olmayan tekrarlamaya ihtiyacınız varsa, tüm güçlülere danışmanızı öneririm ?. Bu, herhangi bir normal ifade tekrar belirtecinin sonuna yerleştirildiğinde, normal ifadenin bu bölümünü mümkün olan en az miktarda metin bulmaya zorlar.

Olduğu söyleniyor, ben ?Dr. Örneğin, örnek girişinizi kullanmak için ((1)bir eşleşme olarak tanımlanır (ikinci bir rparen eksikliğine dikkat edin).

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.