如何在 JavaScript Regexp 中捕获任意数量的组?

IT技术 javascript regex repeat capturing-group
2021-01-22 02:52:58

我希望这行 JavaScript:

"foo bar baz".match(/^(\s*\w+)+$/)

返回类似的东西:

["foo bar baz", "foo", " bar", " baz"]

但它只返回最后捕获的匹配项:

["foo bar baz", " baz"]

有没有办法获得所有捕获的匹配项?

5个回答

当您重复一个捕获组时,在大多数情况下,只保留最后一个捕获;任何先前的捕获都会被覆盖。在某些风格中,例如 .NET,您可以获得所有中间捕获,但 Javascript 则不是这种情况。

也就是说,在 Javascript 中,如果您有一个包含N 个捕获组的模式,则每个匹配项只能捕获N 个字符串,即使其中一些组重复了。

所以一般来说,取决于你需要做什么:

  • 如果这是一个选项,请使用分隔符拆分
  • 而不是匹配/(pattern)+/,也许是匹配/pattern/g,也许是在一个exec循环中
    • 请注意,这两个并不完全等效,但它可能是一种选择
  • 做多级匹配:
    • 在一场比赛中捕获重复的组
    • 然后运行另一个正则表达式来打破匹配

参考


例子

这是<some;words;here>在文本中匹配的示例,使用exec循环,然后拆分;以获取单个单词(另请参见 ideone.com):

var text = "a;b;<c;d;e;f>;g;h;i;<no no no>;j;k;<xx;yy;zz>";

var r = /<(\w+(;\w+)*)>/g;

var match;
while ((match = r.exec(text)) != null) {
  print(match[1].split(";"));
}
// c,d,e,f
// xx,yy,zz

使用的模式是:

      _2__
     /    \
<(\w+(;\w+)*)>
 \__________/
      1

这匹配<word>, <word;another>,<word;another;please>等。重复第 2 组以捕获任意数量的单词,但它只能保留最后一个捕获。整个单词列表由第 1 组捕获;该字符串位于split分号分隔符上。

相关问题

这个怎么样? "foo bar baz".match(/(\w+)+/g)

如果您将其更改为下面的@Jet 正则表达式,它将起作用。"foo bar baz".match(/\w+/g) //=> ["foo", "bar", "baz"]. 它忽略前面匹配的字符串,但仍然是一个合理的选择。
2021-03-21 02:52:58
您的代码有效,但在我的示例中添加全局标志并不能解决问题:"foo bar baz".match(/^(\s*\w+)+$/g) 将返回 ["foo bar baz"]
2021-04-08 02:52:58

除非您对如何拆分字符串有更复杂的要求,否则可以拆分它们,然后用它们返回初始字符串:

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);
这最终只是我需要唤醒我的一条建议,至少对于我当前的应用程序,我不需要比 split() 更复杂的任何东西。
2021-04-06 02:52:58

尝试使用“g”:

"foo bar baz".match(/\w+/g)

您可以使用 LAZY 评估。因此,不要使用 * (GREEDY),而是尝试使用 ? (懒惰的)

正则表达式:(\s*\w+)?

结果:

匹配 1: foo

比赛 2:酒吧

第 3 场比赛:巴兹