re.search和re.match有什么区别?


526

search()Python 模块中的match()函数和有什么区别?re

我已经阅读了文档当前文档),但是我似乎从未记得它。我一直在查找并重新学习它。我希望有人会用示例清楚地回答它,以便(也许)它会贴在我的头上。或者至少我将有一个更好的地方来回答我的问题,并且重新学习它所花的时间会更少。

Answers:


508

re.match锚定在字符串的开头。这与换行无关,因此它与^在模式中使用的方式不同。

重新匹配文档所述

如果字符串开头的零个或多个字符 与正则表达式模式匹配,则返回相应的MatchObject实例。None如果字符串与模式不匹配,则返回;否则返回false。请注意,这与零长度匹配不同。

注意:如果要在字符串中的任何位置找到匹配项,请search() 改用。

re.search搜索整个字符串,如文档所述

扫描字符串以查找正则表达式模式产生匹配项的位置,然后返回相应的MatchObject实例。None如果字符串中没有位置与模式匹配,则返回;否则返回false。请注意,这与在字符串中的某个点找到零长度匹配不同。

因此,如果您需要匹配字符串的开头,或者匹配整个字符串,请使用match。它更快。否则使用search

该文档中有一个专门针对matchvs.的部分search,还涵盖了多行字符串:

基于正则表达式的Python提供两种不同的基本操作:match检查是否有比赛 才刚刚开始的字符串,同时search检查是否有匹配 的任何地方的字符串(这是Perl并默认情况下)。

请注意, 即使使用以:开头的正则表达式match也可能仅在字符串的开头,或者在模式下也紧接换行符之后才匹配 。仅当模式在字符串开头 无论模式如何)或在可选 参数给定的起始位置匹配(无论换行符是否在其前面)时,“ ”操作才会成功。search'^''^'MULTILINEmatchpos

现在,足够的讨论。现在来看一些示例代码:

# 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

包含换行符的字符串呢?
达里尔·斯皮策

25
为什么有人会使用有限match而不是更通用search?是为了速度吗?
Alby 2014年

13
@Alby match比搜索快得多,因此,如果不使用regex.search(“ word”),则可以执行regex.match((。*?)word(。*?)),并获得大量性能数百万个样本。
ivan_bilan's

19
好吧,那真是愚蠢。为什么叫它match?用非直觉的名称为API播种以迫使我阅读文档是否明智?我还是不会做!反叛!
Sammaron

1
使用相同的正则表达式时,@ ivan_bilan match看上去faster比搜索要好一点,但是根据性能测试,您的示例似乎是错误的:stackoverflow.com/questions/180986/…–
baptx

101

search ⇒在字符串中的任何地方找到东西,然后返回一个匹配对象。

match⇒ 在字符串的开头找到一些内容,然后返回匹配对象。


49

re.search 搜索 ES该模式在整个字符串,而re.match没有搜索不到的格局; 如果没有,则除了在字符串开头匹配外,别无选择。


5
为什么要在字符串开头而不是字符串结尾匹配(fullmatch在phyton 3.4中)?
史密斯·约翰斯,2015年

49

match比搜索快得多,因此如果不使用regex.search(“ word”),则可以执行regex.match((。*?)word(。*?)),如果您使用数百万个样品。

@ivan_bilan在上面接受的答案下的评论让我开始思考是否有这样的hack是否真的在加速任何事情,所以让我们找出您将真正获得多少性能。

我准备了以下测试套件:

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功能(略)更快。该测试的实质是避免过度优化代码。


11
+1用于实际调查声明背后的假设,这些假设旨在让您从表面上看得出来-谢谢。
罗伯特·多迪尔

确实,@ ivan_bilan的注释看起来是错误的,但是如果您比较相同的正则表达式,则该match函数仍比该search函数快。您可以通过与进行比较re.search('^python', word)来检查脚本re.match('python', word)(或者re.match('^python', word)相同,但是如果您不阅读文档并且似乎不影响性能
则更

@baptx我不同意该match函数通常更快的说法。该match快的时候,你要搜索开头的字符串时,search速度更快,当你想要搜索整个字符串。这符合常识。这就是@ivan_bilan错误的原因-他曾经match在整个字符串中进行搜索。这就是为什么您是对的-您曾经match在字符串的开头搜索。如果您不同意我的观点,请尝试查找正则表达式,match因为它比做re.search('python', word)同样的事情要快。
Jeyekomon

此外@baptx,作为一个注脚,该re.match('python') 略高于更快re.match('^python')。它一定要是。
Jeyekomon

@Jeyekomon是的,这就是我的意思,match如果要在字符串的开头搜索(例如,使用searchfunction在字符串的开头查找单词),函数会更快一些re.search('^python', word)。但是我发现这很奇怪,如果您告诉search函数在字符串的开头进行搜索,它应该和match函数一样快。
baptx

31

您可以参考以下示例以了解re.matchand.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()

30

区别在于,re.match()误导习惯于Perlgrepsed正则表达式匹配的任何人,并且re.search()不会。:-)

正如约翰·D·库克(John D. Cook)所说,要更加清醒一些,re.match()“表现得好像每个模式都以^开头。” 换句话说,re.match('pattern')等于re.search('^pattern')。因此,它锚定了图案的左侧。但这也没有固定模式的右侧:仍然需要终止$

坦白地说,我认为re.match()应该弃用。我很想知道应该保留它的原因。


4
“表现出好像每个模式都以^开头。” 仅当不使用多行选项时才为true。正确的陈述是“ ...已\ 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.