0

我正在尝试在 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
4

3 回答 3

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"
于 2014-12-08T01:49:35.487 回答
1

在这种情况下,无法单独使用正则表达式来模拟后视的行为,因为字符串中可能有连续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)/
    }
});
于 2014-12-08T03:16:23.327 回答
0

你在这里真正想做的是为一种小语言编写一个解析器。正则表达式擅长某些解析任务,但在许多任务上表现不佳(而且 JS 正则表达式的功能有些不足)。您可能能够找到在特定情况下工作的正则表达式,然后当您的语法规则发生变化时,正则表达式可能难以或不可能更改以反映这一点。下面这个简单的程序具有可读性和可维护性的优点。它完全按照它所说的去做。

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;
}

使用正则表达式

如果您绝对坚持使用正则表达式,则可以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;
}

您将需要调整逻辑来处理字符串的开头和结尾。

这是如何工作的

xbx我们使用正则表达式找到整个字符串。的索引b将是匹配索引的一加,所以我们记录下来。在我们进行下一次匹配之前,我们将lastIndex控制搜索将继续的起点,重置回b,因此它作为任何后续潜在匹配的第一个字符。

于 2014-12-08T03:55:04.637 回答