Apa perbedaan antara re.search dan re.match?

527

Apa perbedaan antara search()dan match()fungsi dalam modul Pythonre ?

Saya sudah membaca dokumentasi ( dokumentasi saat ini ), tetapi sepertinya saya tidak pernah mengingatnya. Saya tetap harus mencarinya dan mempelajarinya kembali. Saya berharap bahwa seseorang akan menjawabnya dengan jelas dengan contoh sehingga (mungkin) itu akan menempel di kepala saya. Atau setidaknya saya akan memiliki tempat yang lebih baik untuk kembali dengan pertanyaan saya dan akan membutuhkan waktu lebih sedikit untuk mempelajarinya kembali.

Daryl Spitzer
sumber

Jawaban:

508

re.matchberlabuh di awal string. Itu tidak ada hubungannya dengan baris baru, jadi tidak sama dengan menggunakan ^dalam pola.

Seperti dokumentasi re.match mengatakan:

Jika nol atau lebih karakter di awal string cocok dengan pola ekspresi reguler, kembalikan MatchObjectinstance yang sesuai . Kembali Nonejika string tidak cocok dengan pola; perhatikan bahwa ini berbeda dari pencocokan panjang nol.

Catatan: Jika Anda ingin mencari kecocokan di mana saja dalam string, gunakan search() sebagai gantinya.

re.searchmencari seluruh string, seperti dokumentasi mengatakan :

Memindai melalui string mencari lokasi di mana pola ekspresi reguler menghasilkan kecocokan, dan mengembalikan MatchObjectcontoh yang sesuai . Kembali Nonejika tidak ada posisi dalam string yang cocok dengan pola; perhatikan bahwa ini berbeda dari menemukan kecocokan panjang nol di beberapa titik dalam string.

Jadi, jika Anda harus mencocokkan pada awal string, atau untuk mencocokkan seluruh penggunaan string match. Lebih cepat. Kalau tidak gunakan search.

Dokumentasi ini memiliki bagian khusus untuk matchvs.search yang juga mencakup string multiline:

Python menawarkan dua operasi primitif berbeda berdasarkan ekspresi reguler: matchmemeriksa kecocokan hanya pada awal string, sementara searchmemeriksa kecocokan di mana saja dalam string (ini yang dilakukan Perl secara default).

Catatan yang matchmungkin berbeda dari search bahkan ketika menggunakan ekspresi reguler yang dimulai dengan '^': '^'cocok hanya pada awal string, atau dalam MULTILINEmode juga segera mengikuti baris baru. Operasi " match" hanya berhasil jika pola cocok pada awal string terlepas dari mode, atau pada posisi awal yang diberikan oleh pos argumen opsional terlepas dari apakah baris baru mendahuluinya.

Sekarang, cukup bicara. Saatnya melihat beberapa kode contoh:

# 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
nosklo
sumber
Bagaimana dengan string yang mengandung baris baru?
Daryl Spitzer
26
Mengapa ada yang menggunakan terbatas matchdaripada lebih umum search? apakah itu untuk kecepatan?
Alby
13
@Setelah kecocokan jauh lebih cepat daripada pencarian, jadi alih-alih melakukan regex.search ("kata") Anda dapat melakukan regex.match ((. *?) Kata (. *?)) Dan mendapatkan banyak kinerja jika Anda bekerja dengan jutaan sampel.
ivan_bilan
20
Yah, itu konyol. Kenapa menyebutnya match? Apakah ini manuver pintar untuk menaburkan API dengan nama yang tidak intuitif untuk memaksa saya membaca dokumentasi? Saya masih tidak akan melakukannya! Pemberontak!
Sammaron
1
@ivan_bilan matchterlihat sedikit fasterdaripada pencarian saat menggunakan ekspresi reguler yang sama tetapi contoh Anda tampaknya salah berdasarkan tes kinerja: stackoverflow.com/questions/180986/…
baptx
101

search ⇒ menemukan sesuatu di string dan mengembalikan objek yang cocok.

match⇒ menemukan sesuatu di awal string dan mengembalikan objek yang cocok.

Dhanasekaran Anbalagan
sumber
49

re.search mencari es untuk pola seluruh string , sedangkan re.matchtidak tidak mencari pola; jika tidak, tidak ada pilihan lain selain mencocokkannya di awal string.

xilun
sumber
5
Mengapa cocok di awal, tetapi tidak sampai akhir string ( fullmatchdalam phyton 3.4)?
Smit Johnth
49

kecocokan jauh lebih cepat daripada pencarian, jadi alih-alih melakukan regex.search ("word") Anda dapat melakukan regex.match ((. *?) word (. *?)) dan mendapatkan banyak kinerja jika Anda bekerja dengan jutaan sampel.

Komentar dari @ivan_bilan di bawah jawaban yang diterima di atas membuat saya berpikir jika peretasan seperti itu benar-benar mempercepat, jadi mari kita cari tahu berapa banyak kinerja yang akan Anda dapatkan.

Saya menyiapkan suite tes berikut:

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)

Saya membuat 10 pengukuran (1M, 2M, ..., 10M kata) yang memberi saya plot berikut:

pertandingan vs pencarian regex plot garis speedtest

Garis yang dihasilkan secara mengejutkan (sebenarnya tidak terlalu mengejutkan) lurus. Dan searchfungsinya (sedikit) lebih cepat mengingat kombinasi pola khusus ini. Moral dari tes ini: Hindari mengoptimalkan kode Anda.

Jeyekomon
sumber
12
+1 untuk benar-benar menyelidiki asumsi di balik pernyataan yang dimaksudkan untuk diambil pada nilai nominal - terima kasih.
Robert Dodier
Memang komentar @ivan_bilan terlihat salah tetapi matchfungsinya masih lebih cepat daripada searchfungsi jika Anda membandingkan ekspresi reguler yang sama. Anda dapat memeriksa di script Anda dengan membandingkan re.search('^python', word)ke re.match('python', word)(atau re.match('^python', word)yang sama tapi lebih mudah untuk memahami jika Anda tidak membaca dokumentasi dan tampaknya tidak mempengaruhi kinerja)
baptx
@ Baptx Saya tidak setuju dengan pernyataan bahwa matchfungsi ini umumnya lebih cepat. Semakin matchcepat ketika Anda ingin mencari di awal string, semakin searchcepat ketika Anda ingin mencari di seluruh string. Yang sesuai dengan akal sehat. Itu sebabnya @ivan_bilan salah - ia biasa matchmencari di seluruh string. Itu sebabnya Anda benar - Anda biasa matchmencari di awal string. Jika Anda tidak setuju dengan saya, cobalah mencari regex untuk matchitu lebih cepat daripada re.search('python', word)dan melakukan pekerjaan yang sama.
Jeyekomon
@aptx Juga, sebagai catatan kaki, re.match('python') ini sedikit lebih cepat daripada re.match('^python'). Itu harus.
Jeyekomon
@Jeyekomon ya itulah yang saya maksud, matchfungsi sedikit lebih cepat jika Anda ingin mencari di awal string (dibandingkan dengan menggunakan searchfungsi untuk menemukan kata di awal string dengan re.search('^python', word)misalnya). Tapi saya menemukan ini aneh, jika Anda memberi tahu searchfungsi untuk mencari di awal string, itu harus secepat matchfungsi.
baptx
31

Anda dapat merujuk contoh di bawah ini untuk memahami cara kerja re.matchdan penelitian ulang

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

re.matchakan kembali none, tetapi re.searchakan kembali abc.

ldR
sumber
3
Hanya ingin menambahkan bahwa pencarian akan mengembalikan objek _sre.SRE_Match (atau Tidak Ada jika tidak ditemukan). Untuk mendapatkan 'abc', Anda perlu menghubungi t.group ()
SanD
30

Bedanya, re.match()menyesatkan siapa pun terbiasa Perl , grep , atau sed pencocokan ekspresi reguler, dan re.search()tidak. :-)

Lebih jernih, Seperti yang dikatakan John D. Cook , re.match()"berperilaku seolah-olah setiap pola memiliki prapengeluaran." Dengan kata lain, re.match('pattern')sama dengan re.search('^pattern'). Jadi itu berlabuh di sisi kiri pola. Tapi itu juga tidak menjangkar sisi kanan pola: itu masih membutuhkan penghentian $.

Terus terang mengingat hal di atas, saya pikir re.match()harus usang. Saya akan tertarik untuk mengetahui alasan itu harus dipertahankan.

KODE-REaD
sumber
4
"Berperilaku seolah-olah setiap pola sudah berpola." hanya benar jika Anda tidak menggunakan opsi multiline. Pernyataan yang benar adalah "... has \ A prepended"
JoelFan
14

re.match berupaya mencocokkan pola di awal string . re.search mencoba untuk mencocokkan pola di seluruh string sampai menemukan kecocokan.

cschol
sumber
3

Jauh lebih pendek:

  • search memindai seluruh string.

  • match hanya memindai awal string.

Mengikuti Ex mengatakannya:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
U10-Maju
sumber