Sự khác biệt giữa re.search và re.match là gì?


527

Sự khác biệt giữa search()và các match()chức năng trong mô-đun Python làre gì?

Tôi đã đọc tài liệu ( tài liệu hiện tại ), nhưng dường như tôi không bao giờ nhớ nó. Tôi tiếp tục phải tìm kiếm nó và học lại nó. Tôi hy vọng rằng ai đó sẽ trả lời rõ ràng bằng các ví dụ để (có lẽ) nó sẽ dính vào đầu tôi. Hoặc ít nhất tôi sẽ có một nơi tốt hơn để trở lại với câu hỏi của mình và sẽ mất ít thời gian hơn để tìm hiểu lại nó.

Câu trả lời:


508

re.matchđược neo ở đầu chuỗi. Điều đó không có gì để làm với các dòng mới, vì vậy nó không giống như sử dụng ^trong mẫu.

Như tài liệu re.match nói:

Nếu không có hoặc nhiều ký tự ở đầu chuỗi khớp với mẫu biểu thức chính quy, hãy trả về một MatchObjectthể hiện tương ứng . Trả về Nonenếu chuỗi không khớp với mẫu; lưu ý rằng điều này khác với một trận đấu có độ dài bằng không.

Lưu ý: Nếu bạn muốn xác định vị trí khớp ở bất kỳ đâu trong chuỗi, search() thay vào đó hãy sử dụng .

re.searchtìm kiếm toàn bộ chuỗi, như tài liệu nói :

Quét qua chuỗi tìm kiếm vị trí trong đó mẫu biểu thức chính quy tạo ra kết quả khớp và trả về một MatchObjectthể hiện tương ứng . Trả về Nonenếu không có vị trí nào trong chuỗi khớp với mẫu; lưu ý rằng điều này khác với việc tìm một kết quả có độ dài bằng 0 tại một số điểm trong chuỗi.

Vì vậy, nếu bạn cần khớp ở đầu chuỗi hoặc để khớp với toàn bộ chuỗi sử dụng match. Nó nhanh hơn Nếu không thì sử dụng search.

Tài liệu này có một phần cụ thể cho matchso vớisearch cũng bao gồm các chuỗi nhiều dòng:

Python cung cấp hai hoạt động nguyên thủy khác nhau dựa trên các biểu thức thông thường: chỉ matchkiểm tra một kết quả khớp ở đầu chuỗi, trong khi searchkiểm tra xem có khớp ở bất kỳ đâu trong chuỗi không (đây là mặc định Perl thực hiện).

Lưu ý rằng matchcó thể khác với search ngay cả khi sử dụng biểu thức chính quy bắt đầu bằng '^': '^'chỉ khớp ở đầu chuỗi hoặc trong MULTILINEchế độ cũng ngay lập tức theo dòng mới. Các “ match” hoạt động thành công chỉ khi các trận đấu mẫu tại đầu của chuỗi không phân biệt chế độ, hoặc tại vị trí bắt đầu được đưa ra bởi tùy chọn pos tham số bất kể đến trước xuống dòng nó.

Bây giờ, nói đủ rồi. Thời gian để xem một số mã ví dụ:

# example code:
string_with_newlines = """something
someotherthing"""

import re

print re.match('some', string_with_newlines) # matches
print re.match('someother', 
               string_with_newlines) # won't match
print re.match('^someother', string_with_newlines, 
               re.MULTILINE) # also won't match
print re.search('someother', 
                string_with_newlines) # finds something
print re.search('^someother', string_with_newlines, 
                re.MULTILINE) # also finds something

m = re.compile('thing$', re.MULTILINE)

print m.match(string_with_newlines) # no match
print m.match(string_with_newlines, pos=4) # matches
print m.search(string_with_newlines, 
               re.MULTILINE) # also matches

Những gì về chuỗi chứa dòng mới?
Daryl Spitzer

26
Tại sao mọi người sẽ sử dụng hạn chế matchchứ không phải chung chung hơn search? nó là cho tốc độ?
Alby

13
Kết hợp @Alby nhanh hơn nhiều so với tìm kiếm, vì vậy thay vì thực hiện regex.search ("từ"), bạn có thể thực hiện từ regex.match ((. *?) (. *?)) Và đạt được hàng tấn hiệu suất nếu bạn đang làm việc với hàng triệu mẫu.
ivan_bilan

20
Chà, thật là ngớ ngẩn. Tại sao gọi nó là match? Đây có phải là một thao tác thông minh để tạo ra các API với các tên không trực quan để buộc tôi đọc tài liệu không? Tôi vẫn sẽ không làm điều đó! Nổi loạn!
Sammaron

1
@ivan_bilan có matchvẻ hơi fastertìm kiếm khi sử dụng cùng một biểu thức thông thường nhưng ví dụ của bạn có vẻ sai theo kiểm tra hiệu suất: stackoverflow.com/questions/180986/
Lỗi

101

search Tìm thứ gì đó ở bất cứ đâu trong chuỗi và trả về một đối tượng khớp.

matchTìm thứ gì đó ở đầu chuỗi và trả về một đối tượng khớp.


49

re.search tìm kiếm es cho mô hình trong suốt chuỗi , trong khi re.matchkhông không tìm kiếm các mô hình; nếu không, nó không có lựa chọn nào khác ngoài việc khớp nó ở đầu chuỗi.


5
Tại sao khớp lúc bắt đầu, nhưng không đến cuối chuỗi ( fullmatchtrong phyton 3.4)?
Smit Johnth 14/07/2015

49

kết hợp nhanh hơn nhiều so với tìm kiếm, vì vậy thay vì thực hiện regex.search ("từ"), bạn có thể thực hiện từ regex.match ((. *?) (. *?)) và đạt được hàng tấn hiệu suất nếu bạn đang làm việc với hàng triệu mẫu.

Nhận xét này từ @ivan_bilan theo câu trả lời được chấp nhận ở trên khiến tôi suy nghĩ liệu việc hack như vậy có thực sự tăng tốc bất cứ điều gì không, vì vậy hãy tìm hiểu xem bạn sẽ đạt được bao nhiêu tấn hiệu suất.

Tôi đã chuẩn bị bộ kiểm tra sau:

import random
import re
import string
import time

LENGTH = 10
LIST_SIZE = 1000000

def generate_word():
    word = [random.choice(string.ascii_lowercase) for _ in range(LENGTH)]
    word = ''.join(word)
    return word

wordlist = [generate_word() for _ in range(LIST_SIZE)]

start = time.time()
[re.search('python', word) for word in wordlist]
print('search:', time.time() - start)

start = time.time()
[re.match('(.*?)python(.*?)', word) for word in wordlist]
print('match:', time.time() - start)

Tôi đã thực hiện 10 phép đo (1M, 2M, ..., 10M từ) cho tôi âm mưu sau:

trận đấu so với tìm kiếm biểu đồ đường tốc độ regex

Các dòng kết quả là đáng ngạc nhiên (thực sự không đáng ngạc nhiên) thẳng. Và searchchức năng là (hơi) nhanh hơn với sự kết hợp mẫu cụ thể này. Đạo đức của bài kiểm tra này: Tránh đánh giá quá cao mã của bạn.


12
+1 để thực sự điều tra các giả định đằng sau một tuyên bố có nghĩa là được thực hiện theo mệnh giá - cảm ơn.
Robert Dodier

Thật vậy, nhận xét của @ivan_bilan có vẻ sai nhưng matchhàm vẫn nhanh hơn searchhàm nếu bạn so sánh cùng một biểu thức thông thường. Bạn có thể kiểm tra tập lệnh của mình bằng cách so sánh re.search('^python', word)với re.match('python', word)(hoặc re.match('^python', word)tương tự nhưng dễ hiểu hơn nếu bạn không đọc tài liệu và dường như không ảnh hưởng đến hiệu suất)
baptx

@baptx Tôi không đồng ý với tuyên bố rằng matchchức năng nói chung là nhanh hơn. Các matchnhanh hơn khi bạn muốn tìm kiếm ở phần đầu của chuỗi, searchlà nhanh hơn khi bạn muốn tìm kiếm suốt chuỗi. Mà tương ứng với ý nghĩa thông thường. Đó là lý do tại sao @ivan_bilan đã sai - anh ấy đã sử dụng matchđể tìm kiếm trong suốt chuỗi. Đó là lý do tại sao bạn đúng - bạn thường matchtìm kiếm ở đầu chuỗi. Nếu bạn không đồng ý với tôi, hãy cố gắng tìm regex vì matchđiều đó nhanh hơn re.search('python', word)và thực hiện cùng một công việc.
Jeyekomon

@baptx Ngoài ra, như một chú thích, các re.match('python') nhẹ nhanh hơn re.match('^python'). Nó phải được.
Jeyekomon

@Jeyekomon vâng, đó là điều tôi muốn nói, matchhàm nhanh hơn một chút nếu bạn muốn tìm kiếm ở đầu chuỗi ( ví dụ như sử dụng searchhàm để tìm một từ ở đầu chuỗi re.search('^python', word)). Nhưng tôi thấy điều này thật kỳ lạ, nếu bạn bảo searchhàm tìm kiếm ở đầu chuỗi, thì nó sẽ nhanh như matchhàm.
baptx

31

Bạn có thể tham khảo ví dụ dưới đây để hiểu hoạt động của re.matchvà re.search

a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)

re.matchsẽ trở lại none, nhưng re.searchsẽ trở lại abc.


3
Chỉ muốn thêm rằng tìm kiếm sẽ trả về đối tượng _sre.SRE_Match (hoặc Không có nếu không tìm thấy). Để có được 'abc', bạn cần gọi t.group ()
SanD

30

Sự khác biệt là, re.match()đánh lừa bất cứ ai quen với Perl , grep hoặc sed kết hợp biểu thức chính quy, và re.search()không. :-)

Tỉnh táo hơn, như John D. Cook nhận xét , re.match()"hành xử như thể mọi mô hình đã ^ chuẩn bị trước". Nói cách khác, re.match('pattern')bằng re.search('^pattern'). Vì vậy, nó neo bên trái của một mô hình. Nhưng nó cũng không neo bên phải của một mẫu: điều đó vẫn đòi hỏi phải chấm dứt $.

Thẳng thắn đưa ra những điều trên, tôi nghĩ re.match()nên phản đối. Tôi sẽ quan tâm để biết lý do nó nên được giữ lại.


4
"hành xử như thể mọi mô hình đều có ^ dự kiến." chỉ đúng nếu bạn không sử dụng tùy chọn đa dòng. Tuyên bố đúng là "... đã \ A trả trước"
JoelFan

14

re.match cố gắng khớp một mẫu ở đầu chuỗi . re.search cố gắng khớp mẫu trong suốt chuỗi cho đến khi tìm thấy kết quả khớp.


3

Ngắn hơn nhiều:

  • search quét qua toàn bộ chuỗi.

  • match chỉ quét phần đầu của chuỗi.

Theo dõi Ex nói rằng:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
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.