python match只捕获第一组和最后一组 - 我误解了什么吗?

时间:2012-06-11 08:16:58

标签: python regex match

我正在开发一个Python脚本,它应该与一系列作者匹配,而我正在使用re - 模块。我遇到了意想不到的事情,我已经能够将它简化为以下非常简单的例子:

>>> import re
>>> s = "$word1$, $word2$, $word3$, $word4$"
>>> word = r'\$(word\d)\$'
>>> m = re.match(word+'(?:, ' + word + r')*', s)
>>> m.groups()
('word1', 'word4')

所以我正在定义一个'基本'正则表达式,它匹配我输入的主要部分,带有一些可识别的功能(在这种情况下我使用$ - 符号),而不是我尝试匹配一个单词加上可能的其他单词列表。

我原本预计m.groups()会显示:

>>> m.groups()
('word1', 'word2', 'word3', 'word4')

但显然我做错了什么。我想知道为什么这个解决方案不起作用以及如何改变它,以便我得到我正在寻找的结果。顺便说一句,这是Linux机器上的Python 2.6.6,如果重要的话。

4 个答案:

答案 0 :(得分:7)

虽然您正在匹配每个$word#$,但第二个捕获组会不断被匹配的最后一个项目替换。

我们来看看调试器:

>>> expr = r"\$(word\d)\$(?:, \$(word\d)\$)*"
>>> c = re.compile(expr, re.DEBUG)
literal 36
subpattern 1
  literal 119
  literal 111
  literal 114
  literal 100
  in
    category category_digit
literal 36
max_repeat 0 65535
  subpattern None
    literal 44
    literal 32
    literal 36
    subpattern 2
      literal 119
      literal 111
      literal 114
      literal 100
      in
        category category_digit
    literal 36

如您所见,只有2个捕获组:subpattern 1subpattern 2。每次找到$word#$时,subpattern 2都会被覆盖。

对于潜在的解决方案,我建议使用re.findall()代替re.match()

>>> s = "$word1$, $word2$, $word3$, $word4$"
>>> authors = re.findall(r"\$(\w+)\$", s)
>>> authors
['word1', 'word2', 'word3', 'word4']

答案 1 :(得分:4)

正则表达式中只有两个捕获组。请改为re.findall(word, s)

regex module支持重复捕获。

答案 2 :(得分:1)

如果您有可选或重复的捕获组,请执行以下操作:

(?:, \$(word\d)\$)*

正则表达式只有一个地方可以返回在该组中捕获的文本,尽管它匹配了字符串的3个部分,因此它包含 last 这样的子字符串。

要查找所有子字符串,您可以使用findall或将字符串标记为其他分隔符。

答案 3 :(得分:0)

你可以避免像这样的正则表达式:

>>> s = "$word1$, $word2$, $word3$, $word4$"
>>> s.replace('$','').split()
['word1,', 'word2,', 'word3,', 'word4']

使用正则表达式,您可以改为使用findall()

>>> re.findall(word, s)
['word1', 'word2', 'word3', 'word4']