ilk eşleşen Regex ile dönüş dizesi


91

Bir normal ifadenin ilk eşleşmesini elde etmek istiyorum.

Bu durumda bir listem var:

text = 'aa33bbb44'
re.findall('\d+',text)

['33', '44']

Listenin ilk öğesini çıkarabilirim:

text = 'aa33bbb44'
re.findall('\d+',text)[0]

'33'

Ancak bu yalnızca en az bir eşleşme olduğunda işe yarar, aksi takdirde bir hata alırım:

text = 'aazzzbbb'
re.findall('\d+',text)[0]

IndexError: liste dizini aralık dışı

Bu durumda bir fonksiyon tanımlayabilirim:

def return_first_match(text):
    try:
        result = re.findall('\d+',text)[0]
    except Exception, IndexError:
        result = ''
    return result

Yeni bir fonksiyon tanımlamadan bu sonucu elde etmenin bir yolu var mı?


Benim için kabul edilen cevap işe yaramadı. Dizi indeksi erişimini kaldırmalı ve len(re.findAll)==0bunun yerine kontrol kullanmalıydım.
Vishal

Yanıtlar:


110

''Varsayılanı, aşağıdakileri ekleyerek normal ifadenize yerleştirebilirsiniz |$:

>>> re.findall('\d+|$', 'aa33bbb44')[0]
'33'
>>> re.findall('\d+|$', 'aazzzbbb')[0]
''
>>> re.findall('\d+|$', '')[0]
''

Ayrıca re.searchbaşkalarının da belirttiği şekilde çalışır :

>>> re.search('\d+|$', 'aa33bbb44').group()
'33'
>>> re.search('\d+|$', 'aazzzbbb').group()
''
>>> re.search('\d+|$', '').group()
''

Harika, search / .group'un findall / [0] 'a göre herhangi bir avantajı var mı?
Luis Ramon Ramirez Rodriguez

6
@LuisRamonRamirezRodriguez Bir eşleşme bulur bulmaz durabilir, metnin geri kalanını işlemesi gerekmez ve tüm eşleşmeleri kaydetmesi gerekmez. Yani daha verimli. Ayrıca @ TimPeters'ın dediği gibi, kelimenin tam anlamıyla "istediğiniz şey budur" . Bu, siz veya bir başkası bir noktada okuyup "Neden findallkullanıldı?" Diye merak ettiğinizde bir avantaj olabilir. .
Stefan Pochmann

43

Yalnızca ilk eşleşmeye ihtiyacınız varsa, re.searchbunun yerine şunu kullanın re.findall:

>>> m = re.search('\d+', 'aa33bbb44')
>>> m.group()
'33'
>>> m = re.search('\d+', 'aazzzbbb')
>>> m.group()
Traceback (most recent call last):
  File "<pyshell#281>", line 1, in <module>
    m.group()
AttributeError: 'NoneType' object has no attribute 'group'

O zaman kullanabilirsin m gibi bir kontrol koşulu olarak kullanabilirsiniz:

>>> m = re.search('\d+', 'aa33bbb44')
>>> if m:
        print('First number found = {}'.format(m.group()))
    else:
        print('Not Found')


First number found = 33

13

Şununla giderdim:

r = re.search("\d+", ch)
result = return r.group(0) if r else ""

re.searchYine de yalnızca dizedeki ilk eşleşmeyi arar , bu yüzden niyetinizi kullanmaktan biraz daha net hale getirdiğini düşünüyorum findall.


9

Hiç kullanmamalısın .findall()- .search()istediğin şey bu. İstediğiniz en soldaki eşleşmeyi bulur (veya Noneeşleşme yoksa döndürür ).

m = re.search(pattern, text)
result = m.group(0) if m else ""

Bunu bir işleve koymak isteyip istemediğiniz size kalmış. Bu var alışılmadık eşleşme bulunursa böyle bir şey inşa neden olan boş bir dize dönmek istiyorum için. İmkansız hakkında karıştı edip .search()kendi buluntular üzerinde bir eşleşme (döndürür Nonedoğru değilse, ya da bir SRE_Matchnesne eğer öyleyse).


3

Yapabilirsin:

x = re.findall('\d+', text)
result = x[0] if len(x) > 0 else ''

Sorunuzun tam olarak normal ifadeyle ilgili olmadığını unutmayın. Aksine, eğer hiç yoksa bir dizideki bir öğeyi nasıl güvenli bir şekilde bulabilirsiniz?


2
Burada 'len (x)> 0'ı basitçe' x 'ile değiştirirdim.
Ulf Aslak

1

Belki bu, daha fazla miktarda girdi verisinin istediğiniz parçayı içermemesi durumunda biraz daha iyi sonuç verir, çünkü daha yüksek maliyetlidir.

def return_first_match(text):
    result = re.findall('\d+',text)
    result = result[0] if result else ""
    return result
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.