0

我有一个看起来像这样的字符串:

var str = "Hello world,  hello >world, hello world!";

...我想用例如再见和地球替换所有的你好,除了以  或> 开头的单词。这些应该被忽略。所以结果应该是:

bye earth,  hello >world, bye earth!

试过这个

str.replace(/(?!\ )hello/gi,'bye'));

但它不起作用。

4

3 回答 3

6

(?!...)向前看。因此,它会查看您要匹配的相同字符hello。您需要的是向后看。

不幸的是,JavaScript 不支持lookbehinds。但是,您可以反转字符串和模式:

reverse = function(s){
    return s.split("").reverse().join("");
}

str = reverse(reverse(str).replace(/olleh(?!;psbn&)/gi, 'eyb'));

我承认,这有点骇人听闻。

或者,可以应用这样的解决方案。它依赖于匹配不能重叠的事实:

str = str.replace(/( hello)|hello/ig, function(match, firstGroup) {
    return firstGroup ? firstGroup : "bye"
});

但是,使用稍微更神秘的技巧(如链接答案中所示),您可以将效率提高大约 2 倍:

str = str.replace(/$/, "bye")                            
         .replace(/( hello)|hello(?=.*(bye))/g, "$1$2")
         .replace(/bye$/, "")

有关完整的解释,请参阅另一篇文章(因为这个问题本质上是重复的)。

至于性能,反转显然是最慢的,因为它必须处理一个数组(两次)。至于其他,回调是最快的,而正则表达式只有一个介于两者之间。所以无论是性能还是可读性,我都推荐回调解决方案。(见基准

于 2013-06-28T16:09:14.010 回答
1

通常,您会使用否定的 look-behind,但 JavaScript 不支持。你可以这样做:

var str = "Hello world,  hello >world, hello world!";
str.replace(/(&(?:nbsp|gt);)?(?:(hello)|world)/gi, 
    function($0, $1, $2){ return $1 ? $0 : $2 ? 'bye' : 'earth'; });
// bye earth,  hello >world, bye earth!
于 2013-06-28T16:08:19.103 回答
1

您可以捕获所有以 或开头的单词>

var str = "Hello world,  hello >world, hello world!";

str = str.replace(/(&(?:gt|nbsp);\w+)|(\bhello\b)|(\bworld\b)/gi, function (match,p1,p2,p3) { 
    if (p1) return p1;
    if (p2) return 'bye';
    if (p3) return 'earth'; });

    console.log(str);
于 2013-06-28T16:15:07.470 回答