Re.search ve re.match arasındaki fark nedir?


526

Python modülündekisearch() ve match()işlevleri arasındaki fark nedir ?re

Belgeleri okudum ( mevcut belgeler ), ama asla hatırlamıyorum. Onu aramaya ve yeniden öğrenmeye devam ediyorum. Birisinin buna örneklerle net bir şekilde cevap vermesini umuyorum, böylece (belki de) kafama yapışacak. Ya da en azından sorumla geri dönmek için daha iyi bir yerim olacak ve bunu yeniden öğrenmek daha az zaman alacak.

Yanıtlar:


508

re.matchdizenin başında sabitlenir. Bunun yeni satırlarla ilgisi yoktur, bu yüzden ^kalıpta kullanmakla aynı şey değildir .

As re.match belgelerine diyor ki:

Dizenin başındaki sıfır veya daha fazla karakter normal ifade modeliyle eşleşiyorsa, ilgili MatchObjectörneği döndürün. İade Nonedize deseni aynı değilse; bunun sıfır uzunluklu eşleşmeden farklı olduğunu unutmayın.

Not: Bir eşleşmeyi dizede herhangi bir yerde bulmak istiyorsanız search() bunun yerine kullanın.

re.searchbelgelerin dediği gibi tüm dizeyi arar :

Normal ifade deseninin eşleştiği bir konumu arayan dizeyi tarayın ve karşılık gelen bir MatchObjectörneği döndürün. Dizede Nonehiçbir konum kalıba uymuyorsa geri dönün ; bunun dizenin bir noktasında sıfır uzunluklu bir eşleşme bulmaktan farklı olduğunu unutmayın.

Bu nedenle, dizenin başında eşleşmeniz veya tüm dize kullanımını eşleştirmeniz gerekiyorsa match. Bu daha hızlı. Aksi takdirde kullanın search.

Dokümantasyon bir sahip için özel bölümüne matchvs.search ayrıca satırlı dizeleri kapsar:

Python, düzenli ifadelere dayalı iki farklı ilkel işlem sunar: yalnızca dizenin başındamatch bir eşleşme olup olmadığını kontrol ederken , dizenin herhangi bir yerinde bir eşleşme olup olmadığını denetler (Perl varsayılan olarak bunu yapar).search

Şununla başlayan normal bir ifade kullanıldığında bile matchfarklı olabileceğini unutmayın : yalnızca dizenin başlangıcında veya bir satırsonunu hemen takip eden modda eşleşir. “ ” Operasyonu başarılı olarak yalnızca desen eşleşmeleri baştan dize moda bakılmaksızın, veya opsiyonel tarafından verilen başlangıç pozisyonunda bir satır önündeki olsun bunun bakılmaksızın argüman.search'^''^'MULTILINEmatchpos

Şimdi, yeterli konuşma. Bazı örnek kodları görme zamanı:

# 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

Yeni satır içeren dizeler ne olacak?
Daryl Spitzer

26
Neden herkes matchdaha genel yerine sınırlı kullansın ki search? hız için mi?
Alby

13
@Alby maçı aramadan çok daha hızlıdır, bu nedenle regex.search ("word") yerine regex.match ((. *?) Word (. *?)) Yapabilir ve birlikte çalışıyorsanız tonlarca performans kazanabilirsiniz. milyonlarca örnek.
ivan_bilan

20
Bu aptalca. Neden aramalıyım match? Belgeleri okumaya zorlamak için API'leri sezgisel olmayan isimlerle tohumlamak akıllıca bir manevra mı? Hala yapmayacağım! İsyancı!
Sammaron

1
@ivan_bilan , aynı normal ifadeyi kullanırken aramadan matchbiraz fasterdaha iyi görünüyor , ancak bir performans testine göre örneğiniz yanlış görünüyor: stackoverflow.com/questions/180986/…
baptx

101

search String dizenin herhangi bir yerinde bir şey bulun ve bir eşleşme nesnesi döndürün.

matchString dizenin başında bir şey bul ve bir eşleşme nesnesi döndür.


49

re.search arama örüntü es dize boyunca oysa re.matchgelmez aramayın deseni; değilse , dizenin başında eşleşmekten başka seçeneği yoktur .


5
Neden başlangıçta eşleşir, ancak dizenin sonuna kadar değil ( fullmatchphyton 3.4'te)?
Smit Johnth

49

eşleşme aramadan çok daha hızlıdır, bu nedenle regex.search ("word") yerine regex.match ((. *?) word (. *?)) yapabilir ve milyonlarca kullanıcıyla çalışıyorsanız tonlarca performans kazanabilirsiniz. örnekleri.

Yukarıdaki kabul cevap altından @ivan_bilan gelen bu açıklama böyle olursa beni düşünmeye itti kesmek o yüzden gerçekten kazanç olacak performansının kaç ton bulalım, aslında bir şey hızlanıyor.

Aşağıdaki test paketini hazırladım:

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)

Bana aşağıdaki çizimi veren 10 ölçüm (1M, 2M, ..., 10M kelime) yaptım:

maç ve arama normal ifadesi en hızlı çizgi grafiği

Ortaya çıkan çizgiler şaşırtıcı bir şekilde (aslında şaşırtıcı değil) düzdür. Ve bu özel desen kombinasyonu göz önüne alındığında searchişlev (biraz) daha hızlıdır . Bu testin ahlaki: Kodunuzu aşırı derecede optimize etmekten kaçının.


12
+1 ifadesinin arkasındaki varsayımları gerçekten araştırdığı için, yüz değerinde alınması gerekiyordu - teşekkürler.
Robert Dodier

Gerçekten de @ivan_bilan'ın yorumu yanlış görünüyor, ancak aynı normal ifadeyi karşılaştırırsanız işlev matchhala işlevden daha hızlıdır search. Sen karşılaştırarak komut kontrol edebilirsiniz re.search('^python', word)etmek re.match('python', word)(ya re.match('^python', word)sen belgeleri okumak yoksa anlamak aynı ama daha kolaydır ve performansını etkilemiyor gibi görünmektedir olan)
baptx

@baptx İşlevin matchgenellikle daha hızlı olduğu ifadesine katılmıyorum . matchArama yapmak istediğiniz zaman hızlıdır başında dize, searcharama yapmak istediğiniz zaman hızlıdır boyunca dize. Bu sağduyuya karşılık gelir. Bu yüzden @ivan_bilan yanlıştı - matchdizede arama yapardı . Bu yüzden haklısın - matchdizenin başında arama yapardın. Bana katılmıyorsanız, matchbunun için daha hızlı re.search('python', word)ve aynı işi yapan regex bulmaya çalışın .
Jeyekomon

Bir dipnot olarak, aynı zamanda @baptx, re.match('python') olduğu daha hızlı marjinal re.match('^python'). Olmak zorunda.
Jeyekomon

@Jeyekomon evet demek matchistediğim, bir dizenin başında arama yapmak istiyorsanız işlev biraz daha hızlıdır ( örneğin searchbir dizenin başında bir sözcük bulmak için işlevi kullanmakla karşılaştırıldığında re.search('^python', word)). Ama bu garip buluyorum, eğer searchfonksiyona bir dizenin başında arama yapmasını söylerseniz, fonksiyon kadar hızlı olmalıdır match.
vaftiz

31

Çalışmasını re.matchve yeniden arama işlemini anlamak için aşağıdaki örneğe başvurabilirsiniz

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

re.matchdönecektir none, ancak re.searchdönecektir abc.


3
Bu aramanın _sre.SRE_Match nesnesini (veya bulunamadığı takdirde) döndüreceğini eklemek ister misiniz? 'Abc' almak için t.group ()
SanD

30

Fark, Perl , grep veya sed normal ifade eşleşmesine re.match()alışkın olan herkesi yanlış yönlendirir ve yapmaz. re.search():-)

Daha aklı başında, John D. Cook'un dediği gibi , re.match()"her model ^ önermiş gibi davranır." Başka bir deyişle, re.match('pattern')eşittir re.search('^pattern'). Böylece bir desenin sol tarafını tutturur. Ama aynı zamanda bir desenin sağ tarafını tutturmaz: bu hala bir sonlandırma gerektirir $.

Açıkçası yukarıdakiler göz önüne alındığında, bence re.match()reddedilmelidir. Saklanması gereken nedenleri bilmek isterim.


4
msgstr "her desenin ^ önceden eklenmiş gibi davranır." yalnızca çok satırlı seçeneğini kullanmıyorsanız doğrudur. Doğru ifade "... \ A eklenmiştir"
JoelFan

14

re.match dizenin başında bir kalıbı eşleştirmeye çalışır . re.search , bir eşleşme bulana kadar deseni dize boyunca eşleştirmeye çalışır.


3

Çok daha kısa:

  • search tüm dizeyi tarar.

  • match dizenin yalnızca başlangıcını tarar.

Aşağıdaki Ex söylüyor:

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