JavaScript正则表达式 - 查找所有可能的匹配,即使是在已经捕获的匹配中

问题描述 投票:0回答:3

我正在尝试使用 JavaScript 的正则表达式从字符串中获取所有可能的匹配项。看来我这样做的方法没有匹配已经匹配的字符串部分。

变量:

var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';

var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;

代码:

var match = string.match(reg);

我得到的所有匹配结果:

A1B1Y:A1B2Y
A1B5Y:A1B6Y
A1B9Y:A1B10Y

我想要的匹配结果:

A1B1Y:A1B2Y
A1B2Y:A1B3Y
A1B5Y:A1B6Y
A1B6Y:A1B7Y
A1B9Y:A1B10Y
A1B10Y:A1B11Y

在我看来,我希望

A1B1Y:A1B2Y
A1B2Y:A1B3Y
一起匹配,即使字符串中的
A1B2Y
需要成为两个匹配的一部分。

javascript regex string match
3个回答
25
投票

无需修改正则表达式,您可以使用

.exec
并操作正则表达式对象的
lastIndex
属性将其设置为在每场比赛后的下半场开始时开始匹配。

var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';
var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;
var matches = [], found;
while (found = reg.exec(string)) {
    matches.push(found[0]);
    reg.lastIndex -= found[0].split(':')[1].length;
}

console.log(matches);
//["A1B1Y:A1B2Y", "A1B2Y:A1B3Y", "A1B5Y:A1B6Y", "A1B6Y:A1B7Y", "A1B9Y:A1B10Y", "A1B10Y:A1B11Y"]

演示


根据 Bergi 的评论,您还可以获取最后一场比赛的索引并将其加 1,这样它就不会从比赛的下半场开始匹配,而是从每场比赛的第二个字符开始尝试匹配开始:

reg.lastIndex = found.index+1;

演示

最终的结果是一样的。不过,Bergi 的更新代码较少,并且执行速度稍快一些。 =]

    


4
投票
match

获得直接结果,但可以通过

RegExp.exec
并对正则表达式进行一些修改来生成结果:

var regex = /A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g; var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y' var arr; var results = []; while ((arr = regex.exec(input)) !== null) { results.push(arr[0] + arr[1]); }

我使用了
零宽度

正前瞻(?=pattern)是为了不消耗文本,以便可以重新匹配重叠部分。


其实,滥用

replace

方法也可以达到同样的效果:


var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y' var results = []; input.replace(/A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g, function ($0, $1) { results.push($0 + $1); return ''; });

不过,既然是
replace

,就做了额外无用的替换工作。

    


3
投票
string.match

那么简单。


原因是你想要重叠的匹配,而

/g

标志并没有给你。


您可以使用前瞻:

var re = /A\d+B\d+Y(?=:A\d+B\d+Y)/g;

但是现在你得到:

string.match(re); // ["A1B1Y", "A1B2Y", "A1B5Y", "A1B6Y", "A1B9Y", "A1B10Y"]

原因是前瞻是零宽度,这意味着它只是说明模式是否位于您要匹配的内容之后;它不包括在比赛中。

您可以使用

exec

尝试抓取您想要的东西。如果正则表达式具有

/g
标志,您可以重复运行
exec
来获取所有匹配项:

// using re from above to get the overlapping matches var m; var matches = []; var re2 = /A\d+B\d+Y:A\d+B\d+Y/g; // make another regex to get what we need while ((m = re.exec(string)) !== null) { // m is a match object, which has the index of the current match matches.push(string.substring(m.index).match(re2)[0]); } matches == [ "A1B1Y:A1B2Y", "A1B2Y:A1B3Y", "A1B5Y:A1B6Y", "A1B6Y:A1B7Y", "A1B9Y:A1B10Y", "A1B10Y:A1B11Y" ];

这是一个实际的小提琴

。打开控制台查看结果 或者,您可以在

:

上拆分原始字符串,然后循环遍历结果数组,当

array[i]
array[i+1]
都按照您想要的方式匹配时,拉出匹配的字符串。
    

© www.soinside.com 2019 - 2024. All rights reserved.