trả về chuỗi với kết quả phù hợp đầu tiên Regex


90

Tôi muốn có được trận đấu đầu tiên của một regex.

Trong trường hợp này, tôi có một danh sách:

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

['33', '44']

Tôi có thể trích xuất phần tử đầu tiên của danh sách:

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

'33'

Nhưng điều đó chỉ hoạt động nếu có ít nhất một kết quả trùng khớp, nếu không, tôi sẽ gặp lỗi:

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

IndexError: danh sách chỉ mục nằm ngoài phạm vi

Trong trường hợp đó, tôi có thể xác định một hàm:

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

Có cách nào để nhận được kết quả đó mà không cần xác định một hàm mới không?


Đối với tôi, câu trả lời được chấp nhận không hoạt động. Tôi đã phải xóa quyền truy cập chỉ mục mảng và sử dụng len(re.findAll)==0kiểm tra thay thế.
Vishal

Câu trả lời:


104

Bạn có thể nhúng ''mặc định vào regex của mình bằng cách thêm |$:

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

Cũng hoạt động với re.searchnhững người khác chỉ ra:

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

Tuyệt vời, search / .group có lợi thế gì hơn findall / [0] không?
Luis Ramon Ramirez Rodriguez,

6
@LuisRamonRamirezRodriguez Chà, nó có thể dừng ngay khi tìm thấy kết quả trùng khớp, không phải xử lý phần còn lại của văn bản và không phải lưu trữ tất cả các kết quả trùng khớp. Vì vậy, nó hiệu quả hơn. Ngoài ra, nó theo nghĩa đen "là những gì bạn muốn" , như @TimPeters đã nói. Đó có thể là một lợi thế khi bạn hoặc ai đó tại một thời điểm nào đó đọc nó và tự hỏi "Tại sao lại được findallsử dụng?" .
Stefan Pochmann

43

Nếu bạn chỉ cần kết quả phù hợp đầu tiên, thì hãy sử dụng re.searchthay vì 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'

Sau đó, bạn có thể sử dụng mlàm điều kiện kiểm tra như:

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


First number found = 33

12

Tôi sẽ đi với:

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

re.searchdù sao cũng chỉ tìm kiếm kết quả phù hợp đầu tiên trong chuỗi, vì vậy tôi nghĩ nó làm cho ý định của bạn rõ ràng hơn một chút so với việc sử dụng findall.


7

Bạn hoàn toàn không nên sử dụng .findall()- đó .search()là những gì bạn muốn. Nó tìm kết quả phù hợp ngoài cùng bên trái, đó là thứ bạn muốn (hoặc trả về Nonenếu không có kết quả phù hợp nào).

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

Bạn có muốn đưa nó vào một chức năng hay không là tùy thuộc vào bạn. Thật bất thường khi muốn trả về một chuỗi trống nếu không tìm thấy kết quả phù hợp nào, đó là lý do tại sao không có gì giống như vậy được tích hợp sẵn. Bạn không thể nhầm lẫn về việc liệu .search()tự nó có tìm thấy kết quả phù hợp hay không (nó trả về Nonenếu không có hoặc một SRE_Matchđối tượng nếu nó đã làm).


3

Bạn có thể làm:

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

Lưu ý rằng câu hỏi của bạn không liên quan chính xác đến regex. Thay vào đó, làm cách nào để bạn tìm thấy một phần tử từ một mảng một cách an toàn, nếu nó không có.


2
Tôi sẽ thay thế 'len (x)> 0' bằng 'x' ở đây.
Ulf Aslak,

1

Có thể điều này sẽ hoạt động tốt hơn một chút trong trường hợp lượng dữ liệu đầu vào lớn hơn không chứa phần mong muốn của bạn vì ngoại trừ chi phí lớn hơn.

def return_first_match(text):
    result = re.findall('\d+',text)
    result = result[0] if result else ""
    return result
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.