re.match
jest zakotwiczony na początku łańcucha. Nie ma to nic wspólnego z nowymi liniami, więc nie jest to to samo, co używanie ^
we wzorcu.
Jak mówi dokumentacja re.match :
Jeśli zero lub więcej znaków na
początku łańcucha pasuje do wzorca wyrażenia regularnego, zwróć odpowiednią MatchObject
instancję. Zwraca, None
jeśli ciąg nie pasuje do wzorca; zauważ, że różni się to od dopasowania o zerowej długości.
Uwaga: jeśli chcesz znaleźć dopasowanie w dowolnym miejscu ciągu, użyj search()
zamiast niego.
re.search
przeszukuje cały ciąg, jak głosi dokumentacja :
Przeszukaj ciąg znaków w poszukiwaniu lokalizacji, w której wzorzec wyrażenia regularnego tworzy dopasowanie, i zwróć odpowiednią MatchObject
instancję. Zwraca, None
jeśli żadna pozycja w ciągu nie pasuje do wzorca; zauważ, że różni się to od znalezienia dopasowania o zerowej długości w pewnym momencie ciągu.
Więc jeśli potrzebujesz dopasować na początku ciągu lub dopasować cały ciąg, użyj match
. To jest szybsze. W przeciwnym razie użyj search
.
Dokumentacja zawiera konkretną sekcję dla match
vs,search
która obejmuje również ciągi wielowierszowe:
Python oferuje dwie różne prymitywne operacje oparte na wyrażeniach regularnych: match
sprawdza dopasowanie
tylko na początku łańcucha, podczas gdy search
sprawdza dopasowanie w
dowolnym miejscu łańcucha (domyślnie robi to Perl).
Zauważ, że match
może się różnić od search
nawet gdy używasz wyrażenia regularnego rozpoczynającego się od '^'
: '^'
dopasowuje tylko na początku łańcucha, lub w
MULTILINE
trybie również bezpośrednio po nowej linii. Operacja „ match
” kończy się powodzeniem tylko wtedy, gdy wzorzec pasuje na początku łańcucha,
niezależnie od trybu, lub w pozycji początkowej podanej przez opcjonalny pos
argument, niezależnie od tego, czy poprzedza go nowa linia.
Teraz dość gadania. Czas zobaczyć przykładowy kod:
# 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
match
a nie bardziej ogólnegosearch
? czy to dla prędkości?match
? Czy to sprytny manewr, aby obsadzić API nieintuicyjnymi nazwami, aby zmusić mnie do przeczytania dokumentacji? Nadal tego nie zrobię! Buntownik!match
wygląda trochę więcejfaster
niż wyszukiwanie, gdy używasz tego samego wyrażenia regularnego, ale twój przykład wydaje się nieprawidłowy zgodnie z testem wydajności: stackoverflow.com/questions/180986/…search
⇒ znajdź coś w dowolnym miejscu ciągu i zwróć obiekt dopasowania.match
⇒ znajdź coś na początku łańcucha i zwróć obiekt dopasowania.źródło
re.search
szukaj es za wzór na całym ciągiem , are.match
nie nie szukać wzoru; jeśli nie, nie ma innego wyjścia, jak dopasować go na początku łańcucha.źródło
fullmatch
w phyton 3.4)?Ten komentarz od @ivan_bilan pod powyższą zaakceptowaną odpowiedzią zmusił mnie do zastanowienia się, czy taki hack naprawdę przyspiesza, więc dowiedzmy się, ile ton wydajności naprawdę zyskasz.
Przygotowałem następujący zestaw testów:
Wykonałem 10 pomiarów (1M, 2M, ..., 10M słów), co dało mi następujący wykres:
Powstałe linie są zaskakująco (a właściwie nie tak zaskakująco) proste. A
search
funkcja jest (nieco) szybsza, biorąc pod uwagę tę konkretną kombinację wzorów. Morał tego testu: Unikaj nadmiernej optymalizacji kodu.źródło
match
funkcja jest nadal szybsza niżsearch
funkcja, jeśli porównasz to samo wyrażenie regularne. Możesz sprawdzić w swoim skrypcie, porównującre.search('^python', word)
dore.match('python', word)
(lubre.match('^python', word)
który jest taki sam, ale łatwiejszy do zrozumienia, jeśli nie czytasz dokumentacji i wydaje się, że nie wpływa na wydajność)match
funkcja jest generalnie szybsza. Immatch
szybciej, gdy chcesz szukać na początku ciągu, tymsearch
szybciej, gdy chcesz przeszukać cały ciąg. Co odpowiada zdrowemu rozsądkowi. Dlatego @ivan_bilan się mylił -match
przeszukiwał cały ciąg. Właśnie dlatego masz rację -match
szukałeś na początku łańcucha. Jeśli się ze mną nie zgadzasz, spróbuj znaleźć wyrażenie regularne,match
ponieważ jest ono szybszere.search('python', word)
i wykonuje tę samą pracę.re.match('python')
jest nieco szybszy niżre.match('^python')
. To musi być.match
funkcja jest nieco szybsza, jeśli chcesz wyszukiwać na początku łańcucha (na przykład przy użyciusearch
funkcji, aby znaleźć słowo na początku łańcuchare.search('^python', word)
). Alesearch
wydaje mi się to dziwne, jeśli powiesz funkcji, by wyszukiwała na początku łańcucha, powinna być tak szybka jakmatch
funkcja.Możesz zapoznać się z poniższym przykładem, aby zrozumieć działanie
re.match
i ponowne wyszukiwaniere.match
wrócinone
, alere.search
wróciabc
.źródło
Różnica polega na tym, że
re.match()
wprowadza w błąd każdego kto jest przyzwyczajony do dopasowywania wyrażeń regularnych Perl , grep lub sed , ire.search()
nie robi tego. :-)Bardziej trzeźwo jak zauważa John D. Cook ,
re.match()
„zachowuje się tak, jakby każdy wzorzec został„ poprzedzony ”. Innymi słowy,re.match('pattern')
jest równyre.search('^pattern')
. Więc zakotwicza lewą stronę wzoru. Ale nie zakotwicza także prawej strony wzoru: nadal wymaga to zakończenia$
.Szczerze mówiąc, biorąc pod uwagę powyższe, uważam, że
re.match()
powinien być przestarzały. Chciałbym poznać powody, dla których należy to zachować.źródło
re.match próbuje dopasować wzór na początku łańcucha . re.search próbuje dopasować wzór w ciągu, dopóki nie znajdzie dopasowania.
źródło
Znacznie krótszy:
search
skanuje cały ciąg.match
skanuje tylko początek ciągu.Następujący Ex mówi:
źródło