提问人:Daryl Spitzer 提问时间:10/8/2008 最后编辑:cottontailDaryl Spitzer 更新时间:6/5/2023 访问量:409057
re.search 和 re.match 有什么区别?
What is the difference between re.search and re.match?
答:
re.match
定位在字符串的开头。这与换行符无关,因此它与在模式中使用不同。^
正如 re.match 文档所说:
如果字符串开头的零个或多个字符与正则表达式模式匹配,则返回 相应的实例。 如果字符串不返回,则返回 匹配模式;请注意,这是 与零长度匹配不同。
MatchObject
None
注意:如果您想找到匹配项 在字符串中的任何位置,请改用。
search()
re.search
搜索整个字符串,如文档所述:
扫描字符串以查找 正则表达式的位置 pattern 生成匹配项,并返回 相应的实例。 如果 字符串与模式匹配;请注意, 这与找到 在 字符串。
MatchObject
None
因此,如果您需要在字符串的开头匹配,或者要匹配整个字符串,请使用 .它更快。否则使用 .match
search
该文档有一个用于匹配
与搜索
的特定部分,其中还涵盖了多行字符串:
Python 提供了两种不同的原语 基于常规的操作 表达式:仅在字符串的开头检查匹配项, 而检查字符串中任何位置的匹配项(这就是什么 Perl 默认这样做)。
match
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
评论
match
search
match
match
faster
MULTILINE
match
search
re.match 尝试匹配字符串开头的模式。re.search 尝试匹配整个字符串的模式,直到找到匹配项。
re.search
在整个字符串中搜索模式,而不搜索模式;如果没有,它别无选择,只能在字符串的开头匹配它。re.match
评论
fullmatch
search
⇒字符串中的任意位置找到某些内容并返回匹配对象。
match
⇒在字符串的开头找到一些东西并返回一个匹配对象。
您可以参考下面的示例来了解 和 re.search 的工作原理re.match
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()
则不会。
更清醒的是,正如约翰·库克(John D. Cook)所说,“表现得好像每个模式都有^前缀。换句话说,等于 .因此,它锚定了图案的左侧。但它也不能锚定模式的右侧:这仍然需要终止 。re.match()
re.match('pattern')
re.search('^pattern')
$
坦率地说,鉴于上述情况,我认为应该弃用。我很想知道应该保留它的原因。re.match()
评论
match 比 search 快得多,所以你可以做 regex.match((.*?) 而不是做 regex.search(“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 字),得出了以下图:
如您所见,搜索模式“python”
比匹配模式更快。'(.*?)python(.*?)'
Python 很聪明。避免试图变得更聪明。
评论
match
search
re.search('^python', word)
re.match('python', word)
re.match('^python', word)
match
match
search
match
match
match
re.search('python', word)
re.match('python')
re.match('^python')
match
search
re.search('^python', word)
search
match
更短:
search
扫描整个字符串。match
仅扫描字符串的开头。
以下 Ex 说:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
评论
快速回答
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)
re.match
锚定在字符串的开头,同时扫描整个字符串。所以在下面的例子中,并匹配同样的东西。re.search
x
y
x = re.match('pat', s) # <--- already anchored at the beginning of string
y = re.search('\Apat', s) # <--- match at the beginning
如果字符串不包含换行符,并且本质上是相同的;差异显示在多行字符串中。在以下示例中,永远不会匹配第二行,而可以使用正确的正则表达式(和标志)。\A
^
re.match
re.search
s = "1\n2"
re.match('2', s, re.M) # no match
re.search('^2', s, re.M) # match
re.search('\A2', s, re.M) # no match <--- mimics `re.match`
中还有另一个函数,它扫描整个字符串,因此它被锚定在字符串的开头和结尾。所以在下面的例子中,和 匹配同样的东西。re
re.fullmatch()
x
y
z
x = re.match('pat\Z', s) # <--- already anchored at the beginning; must match end
y = re.search('\Apat\Z', s) # <--- match at the beginning and end of string
z = re.fullmatch('pat', s) # <--- already anchored at the beginning and end
根据 Jeyekomon 的回答(并使用他们的设置),使用 perfplot 库,我绘制了 timeit 测试的结果,该测试研究了:
- 他们如何比较“模仿”?(第一图)
re.search
re.match
- 他们如何比较“模仿”?(第二图)
re.match
re.search
- 如果将相同的模式传递给他们,他们如何比较?(最后一幅图)
请注意,最后一个模式不会产生相同的输出(因为它锚定在字符串的开头)。re.match
第一个图显示,如果像 一样使用,则速度更快。第二个图支持@Jeyekomon的答案,如果像 一样使用,则显示速度更快。最后一张图显示,如果它们扫描相同的模式,则两者之间几乎没有区别。match
search
match
search
match
search
用于生成性能图的代码。
import re
from random import choices
from string import ascii_lowercase
import matplotlib.pyplot as plt
from perfplot import plot
patterns = [
[re.compile(r'\Aword'), re.compile(r'word')],
[re.compile(r'word'), re.compile(r'(.*?)word')],
[re.compile(r'word')]*2
]
fig, axs = plt.subplots(1, 3, figsize=(20,6), facecolor='white')
for i, (pat1, pat2) in enumerate(patterns):
plt.sca(axs[i])
perfplot.plot(
setup=lambda n: [''.join(choices(ascii_lowercase, k=10)) for _ in range(n)],
kernels=[lambda lst: [*map(pat1.search, lst)], lambda lst: [*map(pat2.match, lst)]],
labels= [f"re.search(r'{pat1.pattern}', w)", f"re.match(r'{pat2.pattern}', w)"],
n_range=[2**k for k in range(24)],
xlabel='Length of list',
equality_check=None
)
fig.suptitle('re.match vs re.search')
fig.tight_layout();
评论
search