Python re
module 中的 search()
和 match()
函数有什么区别?
我读过 documentation (current documentation),但我似乎从来不记得它。我一直不得不查找并重新学习它。我希望有人会用例子清楚地回答它,以便(也许)它会留在我的脑海中。或者至少我会有一个更好的地方来回答我的问题,并且重新学习它需要更少的时间。
re.match
锚定在字符串的开头。这与换行无关,因此与在模式中使用 ^
不同。
正如 re.match documentation 所说:
如果字符串开头的零个或多个字符与正则表达式模式匹配,则返回相应的 MatchObject 实例。如果字符串与模式不匹配,则返回 None;请注意,这与零长度匹配不同。注意:如果要在字符串中的任何位置查找匹配项,请改用 search()。
re.search
搜索整个字符串,如 the documentation says:
扫描字符串以查找正则表达式模式产生匹配的位置,并返回相应的 MatchObject 实例。如果字符串中没有位置与模式匹配,则返回 None;请注意,这与在字符串中的某个点找到零长度匹配不同。
因此,如果您需要匹配字符串的开头,或者匹配整个字符串,请使用 match
。它更快。否则使用 search
。
该文档有一个 specific section for match
vs. search
,它也涵盖了多行字符串:
Python 提供了两种不同的基于正则表达式的原始操作:match 仅在字符串的开头检查匹配,而 search 在字符串中的任何位置检查匹配(这是 Perl 默认所做的)。请注意,即使使用以 '^' 开头的正则表达式,匹配也可能与搜索不同:'^' 仅匹配字符串的开头,或者在 MULTILINE 模式下也紧跟在换行符之后。仅当模式在字符串的开头匹配时,“匹配”操作才会成功,无论模式如何,或者在可选 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
search
⇒ 在字符串中的任何地方找到一些东西并返回一个匹配对象。
match
⇒ 在字符串的开头处找到一些东西并返回一个匹配对象。
match 比 search 快得多,因此如果您使用数百万个数据,您可以执行 regex.match((.*?)word(.*?)) 而不是执行 regex.search("word") 并获得大量性能样品。
This comment from @ivan_bilan under the accepted answer above 让我开始思考这样的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 字),结果如下:
https://i.stack.imgur.com/g55A6.png
如您所见,搜索模式 'python'
比匹配模式 '(.*?)python(.*?)'
更快。
Python 很聪明。避免试图变得更聪明。
match
函数仍然比 search
函数快。您可以通过比较 re.search('^python', word)
和 re.match('python', word)
(或 re.match('^python', word)
来检查您的脚本,如果您不阅读文档并且似乎不会影响性能,这相同但更容易理解)
match
函数通常更快的说法。当您想要搜索 字符串的开头 时,match
会更快,当您想要搜索 整个 字符串时,search
会更快。这符合常识。这就是@ivan_bilan 错误的原因——他使用 match
搜索整个字符串。这就是为什么您是对的 - 您使用 match
在字符串的开头进行搜索。如果您不同意我的观点,请尝试为 match
找到比 re.search('python', word)
更快且完成相同工作的正则表达式。
re.match('python')
略快于 re.match('^python')
。它一定要是。
match
函数会更快一些(与使用 search
函数在字符串开头查找单词 re.search('^python', word)
相比)例子)。但我觉得这很奇怪,如果你告诉 search
函数在字符串的开头进行搜索,它应该和 match
函数一样快。
re.search
搜索模式整个字符串,而re.match
不搜索模式;如果没有,除了在字符串的开头 match 之外别无选择。
fullmatch
)?
您可以参考以下示例来了解 re.match
和 re.search 的工作原理
a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)
re.match
将返回 none
,但 re.search
将返回 abc
。
不同之处在于,re.match()
会误导任何习惯于 Perl、grep 或 sed 正则表达式匹配的人,而 re.search()
会不是。 :-)
更清醒的是,As John D. Cook remarks、re.match()
“表现得好像每个模式都带有 ^ 前缀”。换句话说,re.match('pattern')
等于 re.search('^pattern')
。所以它锚定了图案的左侧。但它也不锚定模式的右侧:仍然需要终止 $
。
坦率地说,鉴于上述情况,我认为 re.match()
应该被弃用。我很想知道应该保留它的原因。
矮得多:
search 扫描整个字符串。
match 仅扫描字符串的开头。
跟随前任说:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
re.match 尝试匹配字符串开头的模式。 re.search 尝试匹配整个字符串中的模式,直到找到匹配项。
快速回答
re.search('test', ' test') # returns a Truthy match object (because the search starts from any index)
re.match('test', ' test') # returns None (because the search start from 0 index)
re.match('test', 'test') # returns a Truthy match object (match at 0 index)
match
而不是更通用的search
呢?是为了速度吗?match
?用不直观的名称为 API 播种以迫使我阅读文档是一种聪明的做法吗?我还是不会!反叛!match
在使用相同的正则表达式时看起来比搜索有点faster
,但根据性能测试,您的示例似乎是错误的:stackoverflow.com/questions/180986/…MULTILINE
的正则表达式时,match
是否与search
相同(产生相同的结果)?