32

我有一个文件,其中包含一堆字符串,例如“size=XXX;”。我第一次尝试 python 的 re 模块并且对以下行为有点迷惑:如果我在正则表达式中使用管道表示“或”,我只会看到返回的那部分匹配。例如:

>>> myfile = open('testfile.txt','r').read()
>>> print re.findall('size=50;',myfile)
['size=50;', 'size=50;', 'size=50;', 'size=50;']
>>> print re.findall('size=51;',myfile)
['size=51;', 'size=51;', 'size=51;']
>>> print re.findall('size=(50|51);',myfile)
['51', '51', '51', '50', '50', '50', '50']
>>> print re.findall(r'size=(50|51);',myfile)
['51', '51', '51', '50', '50', '50', '50']

匹配的“size=”部分消失了。(但它肯定会在搜索中使用,否则会有更多结果)。我究竟做错了什么?

4

6 回答 6

59

您遇到的问题是,如果re.findall尝试匹配的正则表达式捕获组(即括号中的正则表达式部分),那么返回的是组,而不是匹配的字符串。

解决此问题的一种方法是使用非捕获组(以 为前缀?:)。

>>> import re
>>> s = 'size=50;size=51;'
>>> re.findall('size=(?:50|51);', s)
['size=50;', 'size=51;']

如果re.findall尝试匹配的正则表达式没有捕获任何内容,它会返回整个匹配的字符串。

尽管在这种特殊情况下使用字符类可能是最简单的选择,但非捕获组提供了更通用的解决方案。

于 2013-08-25T03:43:00.997 回答
13

当正则表达式包含括号时,它们会将其内容捕获到组中,从而将行为更改findall()为仅返回这些组。这是文档中的相关部分:

(...)

匹配括号内的任何正则表达式,并指示组的开始和结束;可以在执行匹配后检索组的内容,并且可以稍后在字符串中使用\number特殊序列进行匹配,如下所述。要匹配文字'('or ')',请使用\(or \),或将它们包含在字符类中:[(] [)]

为避免这种行为,您可以使用非捕获组:

>>> print re.findall(r'size=(?:50|51);',myfile)
['size=51;', 'size=51;', 'size=51;', 'size=50;', 'size=50;', 'size=50;', 'size=50;']

同样,来自文档:

(?:...)

常规括号的非捕获版本。匹配括号内的任何正则表达式,但组匹配的子字符串在执行匹配后无法检索或稍后在模式中引用。

于 2013-08-25T03:46:03.023 回答
4

在某些情况下,非捕获组不合适,例如使用检测重复单词的正则表达式(来自python 文档的示例)

r'(\b\w+)\s+\1'

在这种情况下,可以使用整场比赛

[groups[0] for groups in re.findall(r'((\b\w+)\s+\2)', text)]

请注意,\1已更改为\2.

于 2018-05-21T09:42:23.307 回答
2

我认为您想要的是使用 [] 而不是 ()。[] 表示字符集,而 () 表示组匹配。尝试这样的事情:

print re.findall('size=5[01];', myfile)
于 2013-08-25T03:43:57.007 回答
2

'size=(50|51);'表示您正在寻找size=50orsize=51但仅匹配50or51部分(注意括号),因此它不返回sign=.

如果你想要sign=退货,你可以这样做:

re.findall('(size=50|size=51);',myfile)
于 2013-08-25T03:33:17.407 回答
0

这是一个干净的解决方案:https ://www.ocpsoft.org/tutorials/regular-expressions/or-in-regex/ 如果网站在这里死掉是示例(尝试 regex101.com):

正则表达式: ^I like (dogs|penguins), but not (lions|tigers).$ 尝试:我喜欢狗,但不喜欢狮子。我喜欢狗,但不喜欢老虎。我喜欢企鹅,但不喜欢狮子。我喜欢企鹅,但不喜欢老虎。

比赛 1 全场比赛 2-29 我喜欢狗,但不喜欢狮子。第 1 组。9-13 只狗 第 2 组。23-28 只狮子...

但使用正则表达式: ^I like (?:dogs|penguins), but not (?:lions|tigers).$ 匹配 1 完整匹配 2-29 我喜欢狗,但不喜欢狮子。Match 2 Full match 30-58 我喜欢狗,但不喜欢老虎。...

于 2021-02-16T17:08:32.970 回答