为什么JavaScript正则表达式中的交替(管道)运算符(|)不能给我两个匹配?

时间:2013-06-29 09:00:24

标签: javascript regex

这是我的正则表达式:

"button:not([DISABLED])".match(/\([^()]+\)|[^()]+/g);

结果是:

["button:not", "([DISABLED])"]

这是对的吗?我糊涂了。因为(管道)运算符|表示“或”,我认为正确的结果是:

["button:not", "[DISABLED]", "([DISABLED])"] 

因为:

["button:not", "[DISABLED]"]

是结果:

"button:not([DISABLED])".match(/[^()]+/g);

和此:

["([DISABLED])"]

是结果:

"button:not([DISABLED])".match(/\([^()]+\)/g);

但是控制台中的结果输出告诉我结果是:

["button:not", "([DISABLED])"]

问题出在哪里?

4 个答案:

答案 0 :(得分:55)

正则表达式

/\([^()]+\)|[^()]+/g

基本上说:有两个选项,匹配(1)\([^()]+\) (2)[^()]+,无论你在哪里看到(/g

让我们迭代您的样本字符串,以便了解获得结果背后的原因。

开始字符串:button:not([DISABLED])

  • 光标从字符 b 开始(实际上它从字符串开始的锚点^开始,但对于此示例,它无关紧要)
  • 在两个可用选项之间, b 只能匹配(2),因为(1)需要开始 (
    • 现在已经开始匹配(2),它会一直通过它,这意味着它会消耗所有不是 ( )
    • 从上面的项目中,它会消耗所有内容,直至 t 字符(因为下一个是 ( 且不匹配{ {1}})因此[^()]+作为第一个匹配的字符串
  • (为清晰起见的空间)
  • 现在光标位于 button:not 。它是否开始匹配任何选项?是的,第一个:(
    • 同样,现在它已经开始匹配(1),它将一直通过它,这意味着它将消耗所有不是 \([^()]+\) < / strong>或 ( 直到找到 ) (如果在消费时发现<<在 ) 之前强> ( ,它会回溯,因为这意味着(1)正则表达式最终不匹配)
    • 现在它消耗所有剩余的字符,直到找到 ) 然后将)作为第二个匹配的字符串
  • (为清晰起见的空间)
  • 由于我们已到达最后一个字符,因此正则表达式处理结束。



编辑:有一个非常有用的online tool,可让您以图形形式查看正则表达式。也许有助于理解正则表达式如何工作:

Regular expression image

您也可以逐步移动光标,看看我上面尝试解释的内容: live link

请注意由([DISABLED])分隔的表达式的优先级:由于JavaScript正则表达式引擎处理字符串的方式,表达式显示的顺序很重要。它将按照给出的顺序评估每个备选方案。如果其中一个选项与末尾匹配,则不会尝试匹配任何其他选项,即使它可以。希望一个例子让它更清晰:

|

答案 1 :(得分:14)

您对交替运算符的理解似乎不正确。它不会查找所有可能的匹配项,仅适用于匹配的第一个(从左到右)。

(a | b)视为“匹配 a b”。

另请参阅:http://www.regular-expressions.info/alternation.html

答案 2 :(得分:0)

我对正则表达式不太了解,但我认为它们的工作方式是给你一个匹配它们的东西,而不是所有可以匹配它们的东西。

所以,|运算符说:“给我一些与左正则表达式匹配的东西,或与正则正则表达式匹配的东西”。

由于你的字符串包含与左正则表达式匹配的东西,你就可以得到它。

答案 3 :(得分:-1)

Regex找到最佳匹配,而不是所有可能的匹配。该正则表达式的最佳匹配是"([DISABLED])",而不是"[DISABLED]",它是“更好”匹配的子集。

考虑以下示例:

"123 456789".match( /[0-9]{4,6}/g )

您想要找到长度在4到6位之间的一个数字。 如果结果将是与正则表达式匹配的所有可能数字,那么它将没有多大用处:

[ "4567", "5678", "6789", "45678", "56789", "456789" ]   // you don't want this