我正在使用javascript正则表达式。 假设我有以下字符串:
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY
我想运行一个正则表达式并使用这种模式得到一个结果:
Match1
1. XXX_1_XXX
2. YYY_1_YYY
Match2
1. XXX_2_XXX
2. YYY_2_YYY
Match3
1. XXX_3_XXX
2. YYY_3_YYY
我尝试过各种变体:
/(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/g
但它仅在第一场比赛时停止。
有没有办法用正则表达式做到这一点?或者我最好将其作为一个数组进行迭代?
答案 0 :(得分:1)
匹配是对字符串的迭代,只有正则表达式的搜索者在上一次匹配结束后之后更多匹配。这可以保证进度,因为空字符串可能导致无限循环。
但您可以按如下方式解决此问题:
var text = "XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY";
var re = /(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/;
while((m = re.exec(text)) !== null) {
alert(JSON.stringify(m));//the result (print)
//do something with m
text = text.substring(m.index+1); //this is not the same as /g
// "/g" would be text = text.substring(m.index+m[0].length+1);
}
该程序的工作原理如下:您不使用 /g
修饰符,因此只进行了一次匹配。
.index
并删除字符串(包括)到该点注意:有一种情况可能会失败:如果空字符串也可以匹配,因为在字符串的末尾,它将保持匹配空字符串并且将导致切割在另一个空字符串中。然而,实现零长度检查很容易。 @Ja͢ck's answer无法解决此问题。
注意:必须考虑的另一个方面是,这不需要“全局”进展。字符串
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_3_YYY YYY_2_YYY
(请注意YYY_|_YYYY
部分中的交换值)将得到相同的结果。
答案 1 :(得分:1)
网站regex101.com是一个很好的资源,可以找出正确的正则表达式。我准备了两个例子:
/([XY]{3}_[0-3]_[XY]{3})/g
将返回:
比赛1
1. [0-9]XXX_1_XXX
比赛2
1. [10-19]XXX_2_XXX
比赛3
1. [20-29]XXX_3_XXX
比赛4
1. [30-39]YYY_1_YYY
比赛5
1. [40-49]YYY_2_YYY
比赛6
1. [50-59]YYY_3_YYY
https://regex101.com/r/xS9eA5/1
和
/(?:([XY]{3}_[0-3]_[XY]{3}) ([XY]{3}_[0-3]_[XY]{3}))/g
将返回:
比赛1
1. [0-9]XXX_1_XXX
2. [10-19]XXX_2_XXX
比赛2
1. [20-29]XXX_3_XXX
2. [30-39]YYY_1_YYY
比赛3
1. [40-49]YYY_2_YYY
2. [50-59]YYY_3_YYY
答案 2 :(得分:1)
问题是在第一次匹配之后,正则表达式引擎的内部索引设置在“YYY _ * _ YYY”之后。
幸运的是,在循环中你可以在“XXX _ * _ XXX”匹配之后将该位置移动到右边:
var s = 'XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY';
var re = /(XXX_(\d)_XXX).*?(YYY_\2_YYY)/g;
while ((match = re.exec(s)) !== null) {
console.log(match[1], match[3]);
// move to start of last match plus length of first submatch
re.lastIndex = match.index + match[1].length;
}
"XXX_1_XXX"
"YYY_1_YYY"
"XXX_2_XXX"
"YYY_2_YYY"
"XXX_3_XXX"
"YYY_3_YYY"