“a或b”正则表达式中的非捕获括号(运算符优先级)

时间:2015-05-14 23:55:03

标签: javascript regex

问题:这是一个错误,还是我的误解?

这是一个接受“A red balloon”或“A blue balloon”的正则表达式,如node.js REP所示。我正在使用'非捕获'?:表单,因为我对捕获颜色不感兴趣:

/A (?:red)|(?:blue) balloon!/.exec("A red balloon!")
=> [ 'A red', index: 0, input: 'A red balloon!' ]

到目前为止,这么好。现在我希望匹配红色或蓝色“球”或“气球”或“弹道导弹”或诸如此类的东西并捕获:

/A (?:red)|(?:blue) (ba.+)!/.exec("A red ball bearing!")
=> [ 'A red', undefined, index: 0, input: 'A red ball bearing!' ]

匹配,但未能捕获第二种形式('滚珠轴承')。 (对于它的价值,regex101.com中的相同形式不匹配。)为了使其捕获,我必须将整个“或”子句包装在另一个非捕获括号中:

/A (?:(?:red)|(?:blue)) (ba.+)!/.exec("A red ball bearing!")
=> [ 'A red ball bearing!', 'ball bearing', index: 0, input: 'A red ball bearing!' ]

所以问题:为什么第二种形式不起作用? (或者为什么它在javascript中匹配而不在regex101.com中?)为什么引入另一个非捕获子句对后续捕获子句有任何影响?或者这表明存在错误?

2 个答案:

答案 0 :(得分:1)

它将其解释为:

A (?:red) 要么 (?:blue) (ba.+)!

这就是它捕获的原因"红色"。一旦你添加了parantheses,它就被正确捕获了。它就像操作顺序一样。

随着parantheses,它变成了:

A red OR blue ba.+ !

答案 1 :(得分:0)

John Strom提供了正确的答案:归结为运算符优先级问题。可以在in the Microsoft Developer Network Library和其他地方找到运营商优先权的权威列表。总结从最高优先级('最严格的绑定')到最低优先级:

  1. \(逃脱)
  2. ()(?:)(?=)[](括号和括号)
  3. *+?{n}{n,}{n,m}(量词)
  4. ^$,\ anymetacharacter,anycharacter(Anchors and Sequences)
  5. 连续的非特殊字符(常规字符)
  6. |(替代)
  7. 正如MSDN文档所指出的那样:

      

    字符的优先级高于交替运算符,允许'm|food'匹配"m""food"。要匹配"mood""food",请使用括号创建子表达式,结果为'(m|f)ood'

    因此原始示例可以更简单地编写为:

    /A (?:red|blue) (ba.*)!/
    

    ...在javascript和regex101中正确检出。