38

这是我的正则表达式:

"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

4 回答 4

61

正则表达式

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

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

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

起始字符串:

button:not([DISABLED])

脚步:

  • 光标从 char 开始(实际上它从字符串的开头锚点开始,但是对于这个例子来说它是无关紧要的)b ^
  • 在两个可用选项之间,b只能匹配(2),因为(1)需要一个起始(
    • 现在它已经开始匹配 (2),它将一直匹配它,这意味着它将消耗所有不是 a (or的东西)
    • 从上面的项目中,它消耗直到(包括)tchar 的所有内容(因为下一个 char 是(不匹配的 a [^()]+),因此保留button:not为第一个匹配的 string
  • (清晰的空间)
  • 现在光标位于(。它是否开始匹配任何选项?是的,第一个:\([^()]+\)
    • 再一次,现在它已经开始匹配(1),它将一直遍历它,这意味着它将消耗不是 a 的所有内容,(或者直到它找到 a (如果在消耗时它在 a之前找到 a ,它将回溯为这将意味着(1)正则表达式最终不匹配)) ) ()
    • 现在它一直消耗所有剩余的字符,直到找到)然后将其([DISABLED])作为第二个匹配的字符串
  • (清晰的空间)
  • 由于我们已经到达最后一个字符,正则表达式处理结束。



编辑:有一个非常有用的在线工具,可让您以图形形式查看正则表达式。也许它有助于理解正则表达式的工作原理:

正则表达式图片

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

请注意由 分隔的表达式的优先级|由于 JavaScript 正则表达式引擎处理字符串的方式,表达式出现的顺序很重要。它将按照给出的顺序评估每个备选方案。如果一个是那些选项匹配到最后,它不会尝试匹配任何其他选项,即使它可以。希望举个例子更清楚:

"aaa".match(/a|aa|aaa/g); // ==> ["a", "a", "a"]
"aaa".match(/aa|aaa|a/g); // ==> ["aa", "a"]
"aaa".match(/aaa|a|aa/g); // ==> ["aaa"]
于 2013-06-29T09:20:08.633 回答
15

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

考虑(a | b)“匹配 匹配”。a b

另见:http ://www.regular-expressions.info/alternation.html

于 2013-06-29T09:17:02.983 回答
0

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

所以,|操作员说:“给我一些匹配左正则表达式的东西,或者匹配右正则表达式的东西”。

由于您的字符串包含与左正则表达式匹配的内容,因此您就知道了。

于 2013-06-29T09:12:45.120 回答
-1

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

考虑以下示例:

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

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

[ "4567", "5678", "6789", "45678", "56789", "456789" ]   // you don't want this
于 2013-06-29T09:12:29.273 回答