re.findall ('(ab | cd)', dize) vs re.findall ('(ab | cd) +', dize)


18

Bir Python düzenli ifadesinde, bu tekil problemle karşılaşıyorum. re.findall('(ab|cd)', string)Ve arasındaki farklar hakkında talimat verebilir misiniz re.findall('(ab|cd)+', string)?

import re

string = 'abcdla'
result = re.findall('(ab|cd)', string)
result2 = re.findall('(ab|cd)+', string)
print(result)
print(result2)

Gerçek Çıktı:

['ab', 'cd']
['cd']

İkinci sonuç neden içermiyor diye kafam karıştı 'ab'?


re.findall ('(ab | cd)', string) ['ab', 'cd'] alır re.findall ('(ab | cd) +', string) ['cd'] alır
rock

Yanıtlar:


15

+bir veya daha fazla kez eşleşen bir tekrar nicelik belirtecidir. Normal ifadede (ab|cd)+, yakalama grubunu (ab|cd) + kullanarak tekrarlıyorsunuz . Bu yalnızca son yinelemeyi yakalar.

Bu davranışın nedeni aşağıdaki gibidir:

Dize söyle abcdlave normal ifade olduğunu söyle (ab|cd)+. Regex motoru, 0 ve 1 konumları arasındaki grup için bir eşleşme bulur abve yakalama grubundan çıkar. Sonra +nicelleştiriciyi görür ve böylece grubu tekrar yakalamaya çalışır ve cdkonum 2 ve 3 arasında çekim yapar .


Tüm yinelemeleri yakalamak istiyorsanız, ve ile eşleşen yinelenen grubu yakalamanız gerekir . Biz iç grup maçları umurumda değil gibi iç grup dışı yakalama yapabilir ile hangi maçlar((ab|cd)+)abcdcd((?:ab|cd)+)abcd

https://www.regular-expressions.info/captureall.html

Dokümanlar'dan,

Diyelim ki !abc!veya gibi bir etiketi eşleştirmek istiyorsunuz !123!. Yalnızca bu ikisi mümkündür ve hangi etiketi aldığınızı anlamak için abcveya öğesini 123bulmak istersiniz. Bu yeterince kolay: !(abc|123)!hile yapacak.

Şimdi etiketin abcve veya 123gibi birden çok dizi içerebileceğini varsayalım . Hızlı ve kolay çözüm . Bu normal ifade gerçekten bu etiketlerle eşleşecektir. Ancak artık etiketin etiketini yakalama grubuna alma gereksinimimizi karşılamıyor. Bu normal ifade eşleştiğinde , yalnızca yakalama grubu saklanır . Eşleştiğinde yalnızca depolar .!abc123!!123abcabc!!(abc|123)+!!abc123!123!123abcabc!abc


+ 'nın yalnızca son yinelemeyi yakaladığını ve bir yakalama grubunun ne olduğunu açıkça belirten bir dokümana bağlanabilir misiniz?
Gulzar

1
@ Gülzar, cevabı güncelledi. Yakalama grupları hakkında buradan okuyabilirsiniz - regular-expressions.info/refcapture.html
Shashank V

@Shanhank, teşekkürler, cevabınız tam olarak ihtiyacım olan şey. içtenlikle teşekkürler
rock

@rock Sorunuzu çözmüşse lütfen cevabı kabul edin.
Shashank V

Tüm normal ifadeyi parantez içine almanıza gerek yoktur. Sadece '(?:ab|cd)+'çalışacak.
Ocak'ta

5

Bunun bir şeyleri daha fazla temizleyip temizlemeyeceğini bilmiyorum, ama basit bir şekilde kaputun altında neler olduğunu hayal etmeye çalışalım, eşleşmeyi kullanarak neler olduğunu özetleyeceğiz

   # group(0) return the matched string the captured groups are returned in groups or you can access them
   # using group(1), group(2).......  in your case there is only one group, one group will capture only 
   # one part so when you do this
   string = 'abcdla'
   print(re.match('(ab|cd)', string).group(0))  # only 'ab' is matched and the group will capture 'ab'
   print(re.match('(ab|cd)+', string).group(0)) # this will match 'abcd'  the group will capture only this part 'cd' the last iteration

findalldizeyi eşleştirin ve aynı anda tüketin, bu REGEX ile neler olduğunu hayal edelim '(ab|cd)':

      'abcdabla' ---> 1:   match: 'ab' |  capture : ab  | left to process:  'cdabla'
      'cdabla'   ---> 2:   match: 'cd' |  capture : cd  | left to process:  'abla'
      'abla'     ---> 3:   match: 'ab' |  capture : ab  | left to process:  'la'
      'la'       ---> 4:   match: '' |  capture : None  | left to process:  ''

      --- final : result captured ['ab', 'cd', 'ab']  

Şimdi aynı şey '(ab|cd)+'

      'abcdabla' ---> 1:   match: 'abcdab' |  capture : 'ab'  | left to process:  'la'
      'la'       ---> 2:   match: '' |  capture : None  | left to process:  ''
      ---> final result :   ['ab']  

Umarım bu biraz şey temizler.


0

Yani, benim için kafa karıştırıcı olan kısım

Desende bir veya daha fazla grup varsa, bir grup listesi döndürün;

docs

size tam bir maç değil, sadece bir yakalama maçı döndürür. Bu grubun yakalanmamasını sağlarsanız (re.findall('(?:ab|cd)+', string), ["abcd"]başlangıçta beklediğim gibi dönecektir


ne beklediğinizden ya da beklemediğinizden emin değilim
RiaD
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.