如何突出显示任意数量的(可能重复的)As,然后是非贪婪匹配器,然后是任意数量的 Bs 等(没有不合理的限制)?
How to highlight any amount of (possibly duplicated) As, followed by non-greedy matcher, then by any amount of Bs etc. (without unreasonable limits)?
下面的示例是我想要的突出显示类型的演示(对于 "a"
、"b"
、"c"
和 "d"
):
var reg = new RegExp("(.*?)([a]{1,})(.*?)([b]{1,})(.*?)([c]{1,})(.*?)([d]{1,})(.*?)", "gi");
var txt = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011".replace(reg,
'<mark></mark><mark></mark><mark></mark><mark></mark>');
document.getElementById("test").innerHTML = txt;
<body>
<div id="test"></div>
</body>
这里的问题显然是 $n
中 n=9
的限制。但是,如果我想对超过四个字符执行此操作(即没有 unreasonable 限制)怎么办?如何解决?
正则表达式不会给你完整的解决方案,它只能是解决方案的一部分。使用正则表达式来隔离各个匹配项,然后遍历这些匹配项并一一进行替换。在这种情况下,迭代是通过将函数定义传递给 .replace()
来完成的,并且该函数本身有另一个 for
循环来进行实际替换。
我还简化了正则表达式,[a]
就是 a
,{1,}
等价于 +
。然后,如果你只是将你想要匹配的字符放在一个数组中,你可以 .join()
将它们放在一起来制作正则表达式,并且这个数组用于函数内部以从最后一个 <mark>...</mark>
向后到第一个。向后移动有助于确保找到的 a
仍然位于整个匹配的前面,直到最后插入 <mark>...</mark>
。它还可以防止获取 <mar<mark>k</mark>>
之类的东西(我将 'k'
添加到数组的原因是为了测试它)。
即使代码突出显示 chars
数组中的 5 个字符,您也可以看到没有任何正则表达式高于 </code>。您可以使这个数组任意长以满足您的需要。我还添加了一个 <code><textarea>
以便您可以看到在 for
循环中生成的正则表达式。
var chars = ['a', 'a', 'b', 'c', 'd', 'k'];
var fillr = '+[^<]*?';
var txt = "OK, abacdk, abcdtk, yaaaxxbyycccczzddddgkkkk0011"
.replace(new RegExp(chars.join(fillr) + '+', 'gi'),
function(m) {
for (var i = chars.length-1; i >= 0; i--) {
var rgx = '^' +
((i!=0)?
('(' + chars.slice(0, i).join(fillr) + fillr + ')'):
'()'
) +
'('+chars[i]+'+)';
document.getElementById('srccode').value += i + '\t' + m + '\n\t' + rgx + '\n';
m = m.replace(new RegExp(rgx, 'gi'), '<mark></mark>');
document.getElementById('srccode').value += '\t' + m + '\n\n';
}
return m.replace(/<\/mark>(\s*)<mark>/gi, '');
}
);
document.getElementById('srccode').value += '\n'+txt;
document.getElementById("test").innerHTML = txt;
<body>
<textarea id="srccode" rows="10" style="width:100%;white-space: nowrap; overflow:scroll;"></textarea>
<div id="test"></div>
</body>
尝试在 replace()
中使用 function as a parameter
这更像是@WiktorStribiżew
提到的动态模式
var reg = new RegExp(["a", "b", "c", "d"].map(a => "([" + a + "]{1,})(.*?)").reduce((a, i) => a + i, "(.*?)"), "gi");
var txt1 = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011"
.replace(reg, (m, ...p) => {
p.pop();//pop string
p.pop();//pop offset
return p.reduce((a, i, ix) => a + (ix % 2 ? "<mark>" + i + '</mark>' : i), '')
});
var txt = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011"
.replace(reg, (m, ...p) => {
p.pop();
p.pop();
return "<br><br>-match-" + m + p.reduce((a, i, ix) => a + "<br>-substring-" + (ix % 2 ? i : "-h-" + i), '')
});
document.getElementById("test").innerHTML = txt1 + txt;
<body>
<div id="test"></div>
</body>
下面的示例是我想要的突出显示类型的演示(对于 "a"
、"b"
、"c"
和 "d"
):
var reg = new RegExp("(.*?)([a]{1,})(.*?)([b]{1,})(.*?)([c]{1,})(.*?)([d]{1,})(.*?)", "gi");
var txt = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011".replace(reg,
'<mark></mark><mark></mark><mark></mark><mark></mark>');
document.getElementById("test").innerHTML = txt;
<body>
<div id="test"></div>
</body>
这里的问题显然是 $n
中 n=9
的限制。但是,如果我想对超过四个字符执行此操作(即没有 unreasonable 限制)怎么办?如何解决?
正则表达式不会给你完整的解决方案,它只能是解决方案的一部分。使用正则表达式来隔离各个匹配项,然后遍历这些匹配项并一一进行替换。在这种情况下,迭代是通过将函数定义传递给 .replace()
来完成的,并且该函数本身有另一个 for
循环来进行实际替换。
我还简化了正则表达式,[a]
就是 a
,{1,}
等价于 +
。然后,如果你只是将你想要匹配的字符放在一个数组中,你可以 .join()
将它们放在一起来制作正则表达式,并且这个数组用于函数内部以从最后一个 <mark>...</mark>
向后到第一个。向后移动有助于确保找到的 a
仍然位于整个匹配的前面,直到最后插入 <mark>...</mark>
。它还可以防止获取 <mar<mark>k</mark>>
之类的东西(我将 'k'
添加到数组的原因是为了测试它)。
即使代码突出显示 chars
数组中的 5 个字符,您也可以看到没有任何正则表达式高于 </code>。您可以使这个数组任意长以满足您的需要。我还添加了一个 <code><textarea>
以便您可以看到在 for
循环中生成的正则表达式。
var chars = ['a', 'a', 'b', 'c', 'd', 'k'];
var fillr = '+[^<]*?';
var txt = "OK, abacdk, abcdtk, yaaaxxbyycccczzddddgkkkk0011"
.replace(new RegExp(chars.join(fillr) + '+', 'gi'),
function(m) {
for (var i = chars.length-1; i >= 0; i--) {
var rgx = '^' +
((i!=0)?
('(' + chars.slice(0, i).join(fillr) + fillr + ')'):
'()'
) +
'('+chars[i]+'+)';
document.getElementById('srccode').value += i + '\t' + m + '\n\t' + rgx + '\n';
m = m.replace(new RegExp(rgx, 'gi'), '<mark></mark>');
document.getElementById('srccode').value += '\t' + m + '\n\n';
}
return m.replace(/<\/mark>(\s*)<mark>/gi, '');
}
);
document.getElementById('srccode').value += '\n'+txt;
document.getElementById("test").innerHTML = txt;
<body>
<textarea id="srccode" rows="10" style="width:100%;white-space: nowrap; overflow:scroll;"></textarea>
<div id="test"></div>
</body>
尝试在 replace()
这更像是@WiktorStribiżew
提到的动态模式var reg = new RegExp(["a", "b", "c", "d"].map(a => "([" + a + "]{1,})(.*?)").reduce((a, i) => a + i, "(.*?)"), "gi");
var txt1 = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011"
.replace(reg, (m, ...p) => {
p.pop();//pop string
p.pop();//pop offset
return p.reduce((a, i, ix) => a + (ix % 2 ? "<mark>" + i + '</mark>' : i), '')
});
var txt = "OK, abacd, abcdt, yaaaxxbyycccczzddddg0011"
.replace(reg, (m, ...p) => {
p.pop();
p.pop();
return "<br><br>-match-" + m + p.reduce((a, i, ix) => a + "<br>-substring-" + (ix % 2 ? i : "-h-" + i), '')
});
document.getElementById("test").innerHTML = txt1 + txt;
<body>
<div id="test"></div>
</body>