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

use*_*362 36 javascript regex

这是我的正则表达式:

"button:not([DISABLED])".match(/\([^()]+\)|[^()]+/g);
Run Code Online (Sandbox Code Playgroud)

结果是:

["button:not", "([DISABLED])"]
Run Code Online (Sandbox Code Playgroud)

这是对的吗?我糊涂了.因为(管道)运算符|意味着"或",我认为正确的结果是:

["button:not", "[DISABLED]", "([DISABLED])"] 
Run Code Online (Sandbox Code Playgroud)

因为这:

["button:not", "[DISABLED]"]
Run Code Online (Sandbox Code Playgroud)

结果是:

"button:not([DISABLED])".match(/[^()]+/g);
Run Code Online (Sandbox Code Playgroud)

还有这个:

["([DISABLED])"]
Run Code Online (Sandbox Code Playgroud)

结果是:

"button:not([DISABLED])".match(/\([^()]+\)/g);
Run Code Online (Sandbox Code Playgroud)

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

["button:not", "([DISABLED])"]
Run Code Online (Sandbox Code Playgroud)

问题出在哪儿?

acd*_*ior 55

正则表达式

/\([^()]+\)|[^()]+/g
Run Code Online (Sandbox Code Playgroud)

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

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

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

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



编辑:有一个非常有用的在线工具,允许您以图形形式查看正则表达式.也许有助于理解正则表达式如何工作:

正则表达图像

您也可以一步一步地移动光标,看看我上面尝试解释的内容:实时链接.

关于表达式的优先级的注意事项|:由于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"]
Run Code Online (Sandbox Code Playgroud)


Fel*_*ing 14

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

考虑(a | b)为"匹配两种 a b ".

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