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

2024-11-19 08:38:00
admin
原创
11
摘要:问题描述:Python 模块中的search()和函数有什么区别?match()`re`我读过Python 2 文档(Python 3 文档),但我似乎从来没有记住它。解决方案 1:re.match`^`位于字符串的开头。这与换行符无关,因此与在模式中使用不同。正如re.match 文档所述:如果字符串开头的...

问题描述:

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

我读过Python 2 文档(Python 3 文档),但我似乎从来没有记住它。


解决方案 1:

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

正如re.match 文档所述:

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

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

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

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

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

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

Python 提供了两种基于正则表达式的不同原始操作:仅在字符串的开头match检查匹配项
,而检查
字符串中任何位置的匹配项(这是 Perl 默认执行的操作)。search

请注意,
即使使用以 开头的正则表达式,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

解决方案 2:

search⇒ 在字符串的任意位置找到某些内容并返回匹配对象。

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

解决方案 3:

匹配比搜索快得多,因此,如果您处理数百万个样本,您可以执行 regex.match((.?)word(.?)) 而不是 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 很聪明。不要试图变得更聪明。

解决方案 4:

re.search 在整个字符串中搜索模式,而不re.match搜索模式;如果没有,它别无选择,只能在字符串的开头进行匹配。

解决方案 5:

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

更严肃地说,正如 John D. Cook 所说,re.match()“表现得好像每个模式都带有 ^ 前缀。”换句话说,re.match('pattern')等于re.search('^pattern')。因此它锚定了模式的左侧。但它也不锚定模式的右侧:这仍然需要终止符$

坦白说,鉴于上述情况,我认为re.match()应该弃用。我很想知道应该保留它的理由。

解决方案 6:

您可以参考以下示例来了解re.match并重新搜索的工作原理

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

re.match会回来none,但re.search会回来abc

解决方案 7:

更简短:

  • search扫描整个字符串。

  • match仅扫描字符串的开头。

以下 Ex 说明了这一点:

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

解决方案 8:

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

解决方案 9:

快速回答

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)

解决方案 10:

re.match位于字符串的开头,而 则re.search扫描整个字符串。因此在下面的例子中,xy匹配相同的内容。

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
2"
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`

中还有另一个函数rere.fullmatch()用于扫描整个字符串,因此它位于字符串的开头和结尾。因此在下面的例子中,xy匹配z相同的内容。

x = re.match('patZ', s)     # <--- already anchored at the beginning; must match end
y = re.search('ApatZ', 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它固定在字符串的开头。)

表演情节

第一个图显示,如果像 一样使用,match速度会更快。第二个图支持@Jeyekomon 的答案,并显示如果像 一样使用,速度会更快。最后一个图显示,如果它们扫描相同的模式,两者之间的差异很小。search`matchsearchmatch`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();
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用