5

我正在编写一个应该与一系列作者匹配的小 Python 脚本,为此我正在使用re-module。我遇到了一些意想不到的事情,我已经能够将其简化为以下非常简单的示例:

>>> 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

4 回答 4

7

尽管您正在匹配 every $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']
于 2012-06-11T08:28:43.967 回答
4

您的正则表达式中只有两个捕获组。试试re.findall(word, s)吧。

regex模块支持重复捕获。

于 2012-06-11T08:23:45.827 回答
1

当您有可选或重复的捕获组时,就像您这样做:

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

正则表达式只有一个位置用于返回该组中捕获的文本,尽管它匹配字符串的 3 个部分,因此它包含最后一个这样的子字符串。

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

于 2012-06-11T08:26:35.237 回答
0

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

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

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

>>> re.findall(word, s)
['word1', 'word2', 'word3', 'word4']
于 2012-06-11T08:20:55.417 回答