用反斜杠替换所有未转义的字符匹配

8

我正在使用正则表达式来替换其他正则表达式中的(,并将其替换为(?:,以将它们转换为非匹配组。我的表达式假定不使用(?X结构,并且看起来像这样:

(
  [^\\]     - Not backslash character
  |^        - Or string beginning
)
(?:
  [\(]      - a bracket
)

不幸的是,在两个匹配项相邻的情况下,这种方法不起作用,就像在这种情况下一样:how((\s+can|\s+do)(\s+i)?)?

image description

使用向后查找,解决方案很简单:

/(?<=[^\\]|^)[\(]/g

但是JavaScript不支持向后查找,那么我该怎么办呢? 我的搜索没有找到任何简单的通用的向后查找替代方案。

3个回答

2

通过反向查找使用后顾

function revStr(str) {
    return str.split('').reverse().join('');
}

var rx = /[(](?=[^\\]|$)/g;
var subst = ":?(";

var data = "how((\\s+can|\\s+do)(\\s+i)?)?";
var res = revStr(revStr(data).replace(rx, subst)); 
document.getElementById("res").value = res;
<input id="res" />

请注意,正则表达式模式也被反转了,这样我们就可以使用向前查看而不是向后查看,替换字符串也被反转了。对于更长的正则表达式来说,这变得太棘手了,但在这种情况下,仍然不那么难以阅读。


2

一种选择是进行两次替换,使用一个标记(我喜欢使用unicode,因为它不太可能在其他地方出现):

var s = 'how((\\s+can|\\s+do)(\\s+i)?)?';
var token = "\u1234";
// Look for the character preceding the ( you want
// to replace. We'll add the token after it.
var patt1 = /([^\\])(?=\()/g;
// The second pattern looks for the token and the (.
// We'll replace both with the desired string.
var patt2 = new RegExp(token + '\\(', 'g');

s = s.replace(patt1, "$1" + token).replace(patt2, "(?:");

console.log(s);

https://jsfiddle.net/48e75wqz/1/


1
很好的解决方法,太棒了 +1 :) 我只是出于兴趣检查了一下:\u1234 ETHIOPIC SYLLABLE SEE - Wiktor Stribiżew
这里有一篇很棒的文章,讲述了如何在JavaScript中模拟后顾(Mimicing Lookbehind),可以进一步阅读。 - Adam Katz
1
正如David Conrad在我的一个回答中指出的那样,不要使用像\u1234这样的“不太可能”的字符——使用一个不是字符的unicode代码点——我现在使用\uFDD1——来自unicode 私有使用区域 - Stephen P

0

字符串示例:

how((\s+can|\s+do)(\s+i)?)?

一行解决方案:

o='how((\\s+can|\\s+do)(\\s+i)?)?';
alert(o.replace(/\\\(/g,9e9).replace(/\(/g,'(?:').replace(/90{9}/g,'\\('))

结果:

how(?:(?:\s+can|\s+do)(?:\s+i)?)?

当然,它也适用于字符串,就像 how((\s+\(can\)|\s+do)(\s+i)?)? 这样的字符串。


第一个捕获组仍然存在。 - Wiktor Stribiżew
@stribizhev也许我误解了OP。看起来我们需要一个完整所需结果的例子。 - AwokeKnowing
我相信所需的结果是"how(?:(?:\s+can|\s+do)(?:\s+i)?)?" - nrabinowitz
@nrabinowitz 如果是这样的话,为什么不直接替换所有( - AwokeKnowing
@AwokeKnowing:因为其中一些是字面上的开括号。 - Wiktor Stribiżew

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