【问题标题】:why does the first alternation not match?为什么第一个交替不匹配?
【发布时间】:2015-05-05 11:06:53
【问题描述】:

我有 following regular expression (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}

我好像不太明白交替模式?

【问题讨论】:

  • 你的意思是你也想捕获${...}?看看regex101.com/r/uR4hJ9/1。您有非捕获组(?:),当您删除?: 时,您将打开捕获。
  • 是的,请 :-),谢谢 :-) 让我们看看有什么不同
  • 这能回答你的问题吗?
  • 还没有:我不明白区别,似乎只有换行符会改变语法?并且您删除了 (?: -> 非捕获组?我想了解一下
  • 您的问题有点令人困惑。您是否还无法在 python 中获取所有匹配项,或者只是网站上的显示有问题?

标签: python regex regex-alternation


【解决方案1】:

为了捕获${...},您需要删除?: 以将非捕获组变成正在捕获组。您也可以为它们命名。另外 [_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*)+
 )
)

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

有关non-capturing groups 的更多信息,请访问 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 demo

【讨论】:

  • 谁投了反对票,请解释一下。我真的厌倦了只来点击向下箭头的人。这是给你的:google.com/…
  • 我没有对你的答案投反对票,但我也没有投赞成票。主要原因是:OP的正则表达式在Python中运行良好(即无需删除?:); [_a-zA-Z0-9] is equal to \w 不正确
  • 这个答案太棒了!
【解决方案2】:

您的模式运行良好,您只需将其与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 的一种方式。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 也许这就是它在其他语言中的工作方式,但 Python 的正则表达式语法并不这样工作。
    • 你是对的,Python正则表达式中没有g修饰符,因为我们使用findall来获取所有匹配项。 OP 的问题是关于在 regex101.com 网站上找不到匹配项
    • 这只是在 regex101 中演示,在 Python 中没有实际使用。
    • 感谢您的帮助,我基本上很感兴趣如何匹配以下stackoverflow.com/questions/30053885/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多