re.searchとre.matchの違いは何ですか?


527

Python モジュールのsearch()match()関数の違いは何ですか?re

ドキュメント現在のドキュメント)を読みましたが、覚えていないようです。私はそれを調べ続け、再学習する必要があります。誰かが例を挙げてはっきりと答えてくれて、(おそらく)頭にくっついてくれることを期待しています。または、少なくとも私は私の質問で戻るためのより良い場所を持っているでしょう、そしてそれがそれを再学習するためにより少ない時間で済むでしょう。

回答:


508

re.match文字列の先頭にアンカーされます。これは改行とは関係がないため^、パターンでの使用とは異なります。

以下のようre.matchドキュメント言います:

文字列先頭の 0個以上の文字 が正規表現パターンに一致するMatchObject場合、対応するインスタンスを返します。None文字列がパターンに一致しない場合は返します。これは長さがゼロの一致とは異なることに注意してください。

注:文字列のどこかで一致を検索する場合は、search() 代わりにを使用してください。

re.searchドキュメントが言うように文字列全体を検索します

文字列スキャンして、正規表現パターンが一致する場所を探し、対応するMatchObjectインスタンスを返します。None文字列のどの位置もパターンに一致しない場合は返します。これは、文字列のある時点で長さがゼロの一致を見つけることとは異なることに注意してください。

したがって、文字列の先頭で照合する必要がある場合、または文字列全体と照合する必要がある場合は、を使用しますmatch。速いです。それ以外の場合はを使用しますsearch

ドキュメントには、vs。の特定のセクションmatchsearchがあり、複数行の文字列もカバーしています。

Pythonは、正規表現に基づいて2つの異なるプリミティブ操作を提供します。文字列の先頭のみmatch一致 をチェックし、文字列の任意の場所で一致をチェックし ます(これはPerlがデフォルトで行うことです)。search

match異なる場合がありsearch 始まる正規表現を用いた場合であっても'^''^'文字列のみの開始時に、またはで試合 MULTILINEもすぐに改行以下のモード。「match」操作は、パターン がモードに関係なく文字列先頭一致する場合、またはpos 改行がその前にあるかどうかに関係なくオプションの引数で指定された開始位置で一致する場合にのみ成功します。

今、十分な話。コード例を見てみましょう。

# 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

改行を含む文字列はどうですか?
Daryl Spitzer、

26
では、なぜ誰matchもが一般的なものではなく限定的なものを使用するのでしょうsearchか?スピードのためですか?
アルビー、2014

13
@Alby一致は検索よりもはるかに高速であるため、regex.search( "word")を実行する代わりに、regex.match((。*?)word(。*?))を実行して、数百万のサンプル。
ivan_bilan 2016年

20
まあ、それは間抜けです。なぜそれを呼び出すのmatchですか?APIに直感的でない名前を付けてドキュメントを読ませるのは賢い操作ですか?まだやらない!反逆者!
サマロン

1
@ivan_bilan matchビットルックスfaster検索と同じ正規表現を使用しますが、あなたの例では、パフォーマンステストによると間違っているようだ:stackoverflow.com/questions/180986/...
baptx

101

search ⇒文字列のどこかを見つけて、一致オブジェクトを返します。

match⇒ 文字列の先頭で何かを見つけて、一致オブジェクトを返します。


49

re.search 検索パターンのためにESを文字列全体のに対し、re.match検索しないパターンを。一致しない場合は、文字列の先頭で一致させる以外に選択肢はありません。


5
開始時に一致するが、文字列の最後まで一致しない理由(fullmatchphyton 3.4)。
Smit Johnth、2015

49

一致は検索よりもはるかに高速であるため、regex.search( "word")を実行する代わりに、regex.match((。*?)word(。*?))を実行して、数百万を処理している場合に大量のパフォーマンスを得ることができます。サンプル。

上記の受け入れられた答えの下での@ivan_bilanからのこのコメントは、そのようなハックが実際に何かをスピードアップしているのではないかと考えさせられました。

次のテストスイートを用意しました。

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)

10回の測定(1M、2M、...、10Mワード)を行った結果、次のプロットが得られました。

正規表現の一致と検索の比較

結果として得られる線は、驚くほど(実際には驚くほどではありませんが)直線です。そして、この特定のパターンの組み合わせを考えると、search関数は(わずかに)高速です。このテストの教訓コードを過度に最適化しないでください。


12
+1は、額面どおりに解釈されることを意図したステートメントの背後にある仮定を実際に調査するためのものです。ありがとうございます。
Robert Dodier

実際、@ ivan_bilanのコメントは間違っているように見えますが、同じ正規表現を比較するとmatchsearch関数は関数よりも高速です。と比較するre.search('^python', word)ことでスクリプトをチェックインできますre.match('python', word)(またはre.match('^python', word)、ドキュメントを読んでおらず、パフォーマンスに影響を与えないようにすると、同じですが理解しやすくなります)
baptx

@baptx match機能が一般的に速いという意見には同意しません。match高速で検索したいとき先頭に文字列の、search検索したいときに高速である全体の文字列。常識と一致します。@ivan_bilanが間違っていたのはそのためですmatch。彼は文字列全体を検索していたのです。それがあなたが正しい理由です-あなたmatchは文字列の先頭で検索するために使用されました。あなたが私に同意しない場合matchは、それよりも速くre.search('python', word)、同じ仕事をするための正規表現を見つけてみてください。
ジェイコモン

@baptxまた、脚注として、re.match('python') よりわずかに高速ですre.match('^python')。それはする必要があります。
ジェイコモン

@Jeyekomonはいそれmatchは私が意味したことです、文字列の先頭で検索する場合、関数は少し高速です(たとえばsearch、関数を使用して文字列の先頭で単語を見つけるのと比べてre.search('^python', word))。しかし、私はこの奇妙なことに気付きます。search文字列の先頭から検索するように関数に指示すると、関数と同じくらい高速になるはずmatchです。
baptx

31

以下の例を参考にしてre.match、re.searchの動作を理解してください。

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

re.match返されますnoneが、re.search戻りますabc


3
検索を追加するだけで、_sre.SRE_Matchオブジェクトが返されます(見つからない場合はNone)。「abc」を取得するには、t.group()を呼び出す必要があります
SanD

30

違いは、Perlgrep、またはsedの正規表現マッチングにre.match()慣れている人を誤解させre.search()ますが、そうではありません。:-)

より落ち着いて、ジョン・D・クックが述べているようにre.match()「あたかもすべてのパターンが先頭に付加されているかのように振る舞います。」つまり、re.match('pattern')はに等しいですre.search('^pattern')。したがって、パターンの左側を固定します。しかし、それはまたパターンの右側を固定しません:それでも終了する必要があります$

率直に言って、私はre.match()非難されるべきだと思います。保持する必要がある理由を知りたいです。


4
「すべてのパターンに^が付加されているかのように動作します。」複数行オプションを使用しない場合にのみ当てはまります。正しい文は「...は\ Aが前に付加されています」
JoelFan

14

re.match は、文字列の先頭のパターンに一致しようとします。re.search は、一致が見つかるまで、文字列全体でパターンの照合を試みます。


3

はるかに短い:

  • search 文字列全体をスキャンします。

  • match 文字列の先頭のみをスキャンします。

Exに続いて言う:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.