re.findall 没有返回完整匹配项?

新手上路,请多包涵

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

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

>>> re.findall('size=51;', myfile)
['size=51;', 'size=51;', 'size=51;']

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

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

匹配的“size=”部分没有了(但肯定是用在搜索中的,不然结果会多)。我究竟做错了什么?

原文由 Ben S. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 708
2 个回答

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

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

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

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

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

原文由 Volatility 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

(...)

匹配括号内的任何正则表达式,并指示组的开始和结束;执行匹配后可以检索组的内容,并且稍后可以在字符串中使用 \number 特殊序列进行匹配,如下所述。 To match the literals '(' or ')' , use \( or \) , or enclose them inside a character class: [(] [)]

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

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

同样,来自文档:

(?:...)

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

原文由 Zero Piraeus 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题