6

我正在尝试这场比赛

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

并得到:

['/links/51f5382e7b7993e335000015']

当我期待时:

['/links/51f5382e7b7993e335000015', '51f5382e7b7993e335000015']

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

移除全局标志后,

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

制作:

[ '/links/51f5382e7b7993e335000015',
  '51f5382e7b7993e335000015',
  index: 0,
  input: '/links/51f5382e7b7993e335000015' ]

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

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

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

如您所见,如果设置了全局修饰符,则使用 String 的 match() 函数将不会返回捕获的组。

然而,

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

似乎可以很好地产生捕获的组。

谢谢你。

4

2 回答 2

3

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

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

强调我的。

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

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

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

第二种情况

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

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


至于你的最后一个例子

'fofoofooofoooo'.match(/f(o+)/g)

同样,由于/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)

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

'fofoofooofoooo'.match(/f(o+)/)

你会得到:

["fo", "o"]  // With index and input element of course.

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

于 2013-07-28T21:18:02.413 回答
1

根据MDN,如果未指定标志,它将返回与RegExp.exec()g相同的结果,后者返回一个包含用于捕获括号的项目的数组。

如果g指定了标志,它将返回一个包含所有匹配项的数组。

此描述与问题中的示例一致,但是您的两个示例是带有橙子的苹果:

  • 您的“链接”正则表达式匹配整个输入字符串一次,可能与一个捕获的组匹配,具体取决于标志。
  • 您的/f(o+)/g正则表达式匹配输入中的几个子字符串。
于 2013-07-28T21:17:37.773 回答