ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我读过 documentation (current documentation),但我似乎从来不记得它。我一直不得不查找并重新学习它。我希望有人会用例子清楚地回答它,以便(也许)它会留在我的脑海中。或者至少我会有一个更好的地方来回答我的问题,并且重新学习它需要更少的时间。


V
Vin

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

那么为什么有人会使用有限的 match 而不是更通用的 search 呢?是为了速度吗?
@Alby 匹配比搜索快得多,因此如果您正在使用,您可以执行 regex.match((.*?)word(.*?)) 而不是执行 regex.search("word") 并获得大量性能数百万个样本。
嗯,这很愚蠢。为什么叫它match?用不直观的名称为 API 播种以迫使我阅读文档是一种聪明的做法吗?我还是不会!反叛!
@ivan_bilan match 在使用相同的正则表达式时看起来比搜索有点 faster,但根据性能测试,您的示例似乎是错误的:stackoverflow.com/questions/180986/…
当使用以 '^' 开头且未指定 MULTILINE 的正则表达式时,match 是否与 search 相同(产生相同的结果)?
R
Ray Toal

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

match ⇒ 在字符串的开头处找到一些东西并返回一个匹配对象。


J
Jeyekomon

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 很聪明。避免试图变得更聪明。


+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) 更快且完成相同工作的正则表达式。
@baptx 另外,作为脚注,re.match('python') 略快于 re.match('^python')。它一定要是。
@Jeyekomon 是的,这就是我的意思,如果您想在字符串的开头进行搜索,match 函数会更快一些(与使用 search 函数在字符串开头查找单词 re.search('^python', word) 相比)例子)。但我觉得这很奇怪,如果你告诉 search 函数在字符串的开头进行搜索,它应该和 match 函数一样快。
t
tzot

re.search 搜索模式整个字符串,而re.match不搜索模式;如果没有,除了在字符串的开头 match 之外别无选择。


为什么在开始时匹配,但直到字符串结尾才匹配(phyton 3.4 中的 fullmatch)?
C
Community

您可以参考以下示例来了解 re.match 和 re.search 的工作原理

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

re.match 将返回 none,但 re.search 将返回 abc


只想添加该搜索将返回 _sre.SRE_Match 对象(如果未找到,则返回 None)。要获得“abc”,您需要调用 t.group()
C
CODE-REaD

不同之处在于,re.match() 会误导任何习惯于 Perlgrepsed 正则表达式匹配的人,而 re.search() 会不是。 :-)

更清醒的是,As John D. Cook remarksre.match()“表现得好像每个模式都带有 ^ 前缀”。换句话说,re.match('pattern') 等于 re.search('^pattern')。所以它锚定了图案的左侧。但它也不锚定模式的右侧:仍然需要终止 $

坦率地说,鉴于上述情况,我认为 re.match() 应该被弃用。我很想知道应该保留它的原因。


“表现得好像每个模式都有 ^ 前缀。”仅当您不使用多行选项时才成立。正确的说法是“...有 \A 前置”
C
Cabbage soup

矮得多:

search 扫描整个字符串。

match 仅扫描字符串的开头。

跟随前任说:

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

c
cschol

re.match 尝试匹配字符串开头的模式。 re.search 尝试匹配整个字符串中的模式,直到找到匹配项。


P
Pall Arpad

快速回答

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)