如何在正则表达式中替换一个捕获组而不是完整匹配?

3

我有这段代码:

let x = "the *quick* brown fox";

let y = x.replace(/[^\\](\*)(.*)(\*)/g, "<strong>$2</strong>");

console.log(y);

它将*quick*替换为<strong>quick</strong>

问题是我希望反斜杠也能被转义,这样\*quick*就不会被转换为<strong>quick</strong>

我通过在正则表达式中要求前面的字符不是斜杠来实现这一点。

不幸的是,这也会使结果中的该字符消失。

因此,结果变成了:

the<strong>quick</strong> brown fox(注意缺少空格)

我想也许我可以将正则表达式的后半部分包装在一个捕获组中,只替换那个部分,但据我所知Javascript的替换功能只适用于完全匹配的字符串。

有没有解决方法?我避免使用完整的markdown库,因为我只需要处理几种情况(加粗和斜体),所以我试图保持简单。


你可以使用正则表达式捕获 ([^\\])(\*)(.*)(\*),并用 $1<strong>$3</strong> 替换,但这也不正确,因为反斜杠本身可能会被转义。贪婪的 .* 也可能效果不佳...还有混合强调标记的情况...最好使用一个库,或者至少编写不基于正则表达式替换的代码。 - Ry-
在我的测试中,我注意到$1<strong>$3</strong>非常接近但并不完全符合要求。我有点希望我只需要解决这个小问题,而不必迁移到一个完整的库。 - Ryan Peschel
1个回答

3
使用负回顾后发现,使得该字符不包含在匹配中。这也允许它在字符串开头进行匹配(您的正则表达式要求在匹配之前存在一个字符)。

let x = "the *quick* brown fox";
let y = x.replace(/(?<!\\)(\*)(.*)(\*)/g, "<strong>$2</strong>");
console.log(y);

x = "the \\*quick* brown fox";
y = x.replace(/(?<!\\)(\*)(.*)(\*)/g, "<strong>$2</strong>");
console.log(y);

负回顾后断言是 JavaScript 的一个新特性,如果你需要支持老版本的浏览器,可以把其前面的字符放到另一个捕获组里,并复制到替换结果中。为了解决开头的匹配问题,可使其匹配字符串的开头或非反斜杠字符。

let x = "the \\*quick* brown fox";
let y = x.replace(/(^|[^\\])(\*)(.*)(\*)/g, "$1<strong>$3</strong>");
console.log(y);

x = "the *quick* brown fox";
y = x.replace(/(^|[^\\])(\*)(.*)(\*)/g, "$1<strong>$3</strong>");
console.log(y);


哦,太棒了,这个很好用!是的,我知道负向后瞻只有71%的浏览器支持。但是替代方案只需要额外两个字符,所以最好还是使用它?除非Babel可以为您转换负向后瞻? - Ryan Peschel
1
不,Babel无法转换这个,因为存在太多复杂性。 - Barmar
好的,我会选择第二个选项。谢谢! - Ryan Peschel
啊,抱歉我发现了一个问题(虽然不确定是否可以修复?)。如果您输入反斜杠,则输出中仍会存在反斜杠。理想情况下,输入“the *quick* brown fox”应该输出“the quick brown fox”(没有反斜杠,没有强调),你懂的? - Ryan Peschel
其实算了,我想我解决了。在我通过正则表达式运行它之后,只需执行 y = y.replace(/\\/g, ""); 即可。 - Ryan Peschel

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