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


81

我希望这行JavaScript:

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

返回类似:

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

但相反,它仅返回最后捕获的匹配项:

["foo bar baz", " baz"]

有没有办法获取所有捕获的比赛?

Answers:


90

在大多数情况下,当您重复一个捕获组时,仅保留最后一个捕获。以前的任何捕获都将被覆盖。以某种形式,例如.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,此字符串位于分号分隔符上。

相关问题


7

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


您的代码有效,但是在我的示例中添加全局标志不能解决问题:“ foo bar baz” .match(/ ^(\ s * \ w +)+ $ / g)将返回[“ foo bar baz”]
disc0dancer

如果将其更改为下面的@Jet正则表达式,它将起作用。"foo bar baz".match(/\w+/g) //=> ["foo", "bar", "baz"]。它忽略了前面的匹配字符串,但仍然是一个合理的选择。
杰德·施耐德

6

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

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);

1
最终,这只是我需要唤醒我的一个建议,至少对于我当前的应用程序,我不需要比split()更复杂的东西。
Hephaestus 2014年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.