为什么String.match()在出现全局标志时不会产生预期的结果?

Dmi*_*sky 6 javascript regex

我正在尝试这场比赛

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g)
Run Code Online (Sandbox Code Playgroud)

得到了:

['/links/51f5382e7b7993e335000015']
Run Code Online (Sandbox Code Playgroud)

虽然我在期待:

['/links/51f5382e7b7993e335000015', '51f5382e7b7993e335000015']
Run Code Online (Sandbox Code Playgroud)

在我删除全局标志之前我没有运气,我认为这不会影响我的结果!

删除全局标志后,

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/)
Run Code Online (Sandbox Code Playgroud)

制作:

[ '/links/51f5382e7b7993e335000015',
  '51f5382e7b7993e335000015',
  index: 0,
  input: '/links/51f5382e7b7993e335000015' ]
Run Code Online (Sandbox Code Playgroud)

这很酷,但阅读我无法弄清楚的文档:

  • 为什么第一种形式不起作用
  • 为什么全局标志会干扰()匹配
  • 如何在没有indexinput属性的情况下获得我的预期结果

JavaScript Regex和Submatches上,最佳答案是:

如果设置了global修饰符,使用String的match()函数将不会返回捕获的组,如您所知.

然而,

> 'fofoofooofoooo'.match(/f(o+)/g) 
["fo", "foo", "fooo", "foooo"]
Run Code Online (Sandbox Code Playgroud)

似乎产生被捕群体就好了.

谢谢.

Roh*_*ain 3

这个 msdn 文档中获取 match 方法:

如果未设置全局标志 (g),则数组的元素 0 包含整个匹配项,而元素 1 到 n 包含任何子匹配项。此行为与未设置全局标志时 exec 方法(正则表达式)(JavaScript) 的行为相同。如果设置了全局标志,则元素 0 到 n 包含发生的所有匹配项。

强调我的。

所以,在你的第一种情况下:

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g)
Run Code Online (Sandbox Code Playgroud)

由于/g设置了修饰符,它将仅返回发生的完整匹配,而不是子匹配。这就是为什么你只得到一个包含单个元素的数组。因为该正则表达式只有 1 个匹配项。

第二种情况

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/)
Run Code Online (Sandbox Code Playgroud)

/g未设置修饰符。所以数组包含0th索引处的完整匹配。数组中的其他元素(第一个索引)是子匹配 - 在本例中是第一个捕获组。


至于你的最后一个例子

'fofoofooofoooo'.match(/f(o+)/g)
Run Code Online (Sandbox Code Playgroud)

同样,由于/g设置了修饰符,它将返回字符串中的所有匹配项,而不是子匹配项。因此,在字符串中,正则表达式f(o+)匹配 4 次:

fo    - 1st complete match (sub-match 'o' in 1st captured group ignored)
foo   - 2nd complete match (sub-match 'oo' ignored)
fooo  - 3rd complete match (sub-match 'ooo' ignored)
foooo - 4th complete match (sub-match 'oooo' ignored)
Run Code Online (Sandbox Code Playgroud)

如果您使用最后一个不带/g修饰符的正则表达式,则对于第一个匹配,您将获得每个子匹配作为单独的元素。尝试:

'fofoofooofoooo'.match(/f(o+)/)
Run Code Online (Sandbox Code Playgroud)

你会得到:

["fo", "o"]  // With index and input element of course.
Run Code Online (Sandbox Code Playgroud)

如果没有,/g它只会在第一个匹配 ( fo) 之后停止,并返回整个匹配和子匹配。