我正在尝试在JavaScript中创建一个匹配字符b
的正则表达式,如果字符a
不是之前或之后。
显然,JavaScript正则表达式没有容易实现的负面观察,使任务变得困难。我提出了以下一个,但它不起作用。
"ddabdd".replace(new RegExp('(?:(?![a]b(?![a])))*b(?![a])', 'i'),"c");
是我能想到的最好的。在这里,b
不应该匹配,因为它前面有a
,但它匹配。
关于我想要实现的目标的一些例子
"ddbdd" matches the b
"b" matches the b
"ddb" matches the b
"bdd" matches the b
"ddabdd" or "ddbadd" does not match the b
答案 0 :(得分:4)
似乎您可以使用包含字符串锚点的开头或“b”之前的否定字符类的捕获组,同时使用Negative Lookahead断言“a”也不会跟随。然后,您只需在替换调用中引用$1
以及替换字符串的其余部分。
var s = 'ddbdd b ddb bdd ddabdd ddabdd ddbadd';
var r = s.replace(/(^|[^a])b(?!a)/gi, '$1c');
console.log(r); //=> "ddcdd c ddc cdd ddabdd ddabdd ddbadd"
编辑:由于@nhahtdh指出了关于连续字符的评论,您可以考虑回调。
var s = 'ddbdd b ddb bdd ddabdd ddabdd ddbadd sdfbbfds';
var r = s.replace(/(a)?b(?!a)/gi, function($0, $1) {
return $1 ? $0 : 'c';
});
console.log(r); //=> "ddcdd c ddc cdd ddabdd ddabdd ddbadd sdfccfds"
答案 1 :(得分:1)
在这种情况下,无法单独使用regex 来模拟后视的行为,因为字符串中可能存在连续的b
,这需要零宽度属性一个后视来检查前一个字符。
由于后视中的条件非常简单,您可以在替换功能中检查它:
inputString.replace(/b(?!a)/gi, function ($0, idx, str) {
if (idx == 0 || !/a/i.test(str[idx - 1])) { // Equivalent to (?<!a)
return 'c';
} else {
return $0; // $0 is the text matched by /b(?!a)/
}
});
答案 2 :(得分:0)
你真正要做的就是为一种小语言编写一个解析器。 Regexp擅长一些解析任务,但很多很糟糕(而且JS regexp的功能有点不足)。您可能能够找到在特定情况下工作的正则表达式,然后当您的语法规则发生更改时,可能难以或无法更改正则表达式以反映该情况。下面的简单程序具有可读性和可维护性的优点。它完全符合它所说的。
function find_bs(str) {
var indexes = [];
for (var i = 0; i < str.length; i++) {
if (str[i] === 'b' && str[i-1] !== 'a' && str[i+1] !== 'a')
indexes.push(i);
}
return indexes;
}
如果您绝对坚持使用正则表达式,则可以使用regexp上的lastIndex
属性与RegExp.exec
一起重置的技巧:
function find_bs(str) {
var indexes = [];
var regexp = /.b[^a]|[^a]b./g;
var matches;
while (matches = regexp.exec(str)) {
indexes.push(matches.index + 1);
regexp.lastIndex -= 2;
}
return indexes;
}
您需要调整逻辑来处理字符串的开头和结尾。
如何运作
我们使用regexp找到整个xbx
字符串。 b
的索引将是一个加上匹配的索引,因此我们记录下来。在我们进行下一场比赛之前,我们会将lastIndex
重置为b
,该{{1}}管理搜索将继续的起点,因此它将作为任何后续潜在匹配的第一个字符。< / p>