正则表达式:使用量词捕获多个组

8
考虑以下代码:
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">

var str = '<12> rnbqkb-r Rnbq-b-r ';

var pat1 = new RegExp('^\\<12\\> ([rnbqkpRNBQKP-]{8}) ([rnbqkpRNBQKP-]{8})');
var pat2 = new RegExp('^\\<12\\> ([rnbqkp RNBQKP-]{8}){2}');
var pat3 = new RegExp('^\\<12\\> ([rnbqkp RNBQKP-]{8}){2}?');

document.write(str.match(pat1));
document.write('<br />');
document.write(str.match(pat2));
document.write('<br />');
document.write(str.match(pat3));

</script>
</body>
</html>

它产生的是:
<12> rnbqkb-r Rnbq-b-r,rnbqkb-r,Rnbq-b-r
<12> rnbqkb-r Rnbq-b-, Rnbq-b-
<12> rnbqkb-r Rnbq-b-, Rnbq-b-

作为输出。
为什么模式pat2和pat3都不能捕获第一组rnbqkb-r?我希望能够捕获所有的组,而不必像模式pat1那样明确地重复它们。
2个回答

8
为什么模式pat2和pat3都无法捕获第一组rnbqkb-r?
因为在每个8个字符序列的末尾有空格,而你的正则表达式pat2和pat3不允许这种情况。
我想捕获所有组,而不必像模式pat1一样明确重复它们。你不能这样做。当你的正则表达式只包含一个组时,在JavaScript中不可能捕获两个组。
组是通过括号定义的。匹配结果将包含与正则表达式中括号对数相同的组数(除了修改后的括号,如(?:...),它不会计入匹配组数)。想要在匹配结果中得到两个独立的组匹配?在你的正则表达式中定义两个独立的组。
如果一个组可以多次匹配,则该组的值将是它最后匹配的内容。所有先前为该组匹配的内容都将被其最后一个匹配所覆盖。
试试:
var pat1 = /^<12> ((?:[rnbqkp-]{8} ?)*)/i,
    match = str.match(pat1);

if (match) {
  match[1].split(/\s+/);  // ["rnbqkb-r", "Rnbq-b-r", ""]
}

注意:

  • 如果你不想要最后一个空数组值,请先修剪 str
  • 通常情况下,优先选择正则表达式字面量表示法(/expression/)。只有在从动态值生成表达式时才使用 new RegExp()
  • <> 不是特殊字符,你不需要转义它们。

截至2019年,这仍然是正确的吗?我刚遇到了这个问题,找不到比你的回答更新的答案。 - Sheraff
即使到了2020年,这仍然是真实的。 - Tomalak

2

空格包含在模式中。无论如何,我尝试了'^\<12\> ([rnbqkp RNBQKP-]{9}){2}'和'^\<12\> ([rnbqkp RNBQKP-]{9}){2}?',两者都导致<12> rnbqkb-r Rnbq-b-r,Rnbq-b-r。再次说明,第一组未被捕获。 - chessweb
请查看http://refiddle.com/2xh,替换8/9并查看差异。但这并不是您问题的根源。 - Prinzhorn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接