2

我有以下我不理解的正则表达式(Python)。为什么它也与第一个交替不匹配?

正则表达式(间隔以便更好地理解):

(?:
  \$\{
    (?P<braced>
       [_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z][_a-zA-Z0-9]*)+
    )
  \}
)
|   ### SECOND ALTERNATION ###
(?:
  \$
   (?P<named>
     [_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z][_a-zA-Z0-9]*)+
   )
)

测试字符串:

asdasd $asd:sd + ${asd123:asd} $HOME $$asd

搭配的东西:

asdasd $asd:sd + ${asd123:asd} $HOME $$asd

根据上面的正则表达式模式,也应该出现第一个交替,即:

${asd123:asd}

看来我不太明白交替模式?

4

3 回答 3

2

为了捕获${...},您需要删除?:以将非捕获组转换为捕获组。您也可以为它们命名。[_a-zA-Z0-9]也等于\w,因此我们可以稍微缩短您的正则表达式:

(?P<Alternation1>
 \$\{(?P<braced>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+)
 \}
 )
 |
 (?P<Alternation2>
  \$(?P<named>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+
 )
)

看看演示。此正则表达式需要使用x选项(以及gregex101.com 上的选项来显示所有匹配项,在 Python 中,您将使用findallor finditer)。

有关非捕获组的更多信息,请参见 SO 和regular-expressions.info

要在 Python 中获取所有匹配项,您可以finditer像这样使用:

import re
p = re.compile(ur'''(?P<Alternation1>
     \$\{(?P<braced>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+)
     \}
     )
     |
     (?P<Alternation2>
      \$(?P<named>[_a-zA-Z][a-zA-Z0-9]*(?::[_a-zA-Z]\w*)+
     )
    )
''', re.VERBOSE)
test_str = u"asdasd $asd:sd + ${asd123:asd} $HOME $$asd"

print [x for x in re.findall(p, test_str)]

IDEONE 演示

于 2015-05-05T11:20:18.560 回答
1

您的模式运行良好,您只需要使用它finditer来执行全局研究并获得整个匹配:

>>> for m in re.finditer(pattern, text):
...     print 'whole match: %s' (m.group(0))
...     print 'group "braced": %s' % (m.group('braced'))
...     print 'group "named": %s\n' % (m.group('named'))

findall (也执行全局研究)的问题是,当您在模式中有捕获组时,结果仅包含捕获组内容的列表,而不包含整个匹配结果。因此,按照建议将所有内容包含在捕获组中通过 stribizhev 可以是一种方式findall)。

于 2015-05-05T11:30:15.637 回答
0

您需要添加g修饰符以获取 regex101.com 上的所有匹配项

https://www.regex101.com/r/nP8pK0/1

于 2015-05-05T11:17:09.997 回答