那里的人应该是一个简单的问题:
如果我运行这个JavaScript:
var regex = new RegExp("(?!cat)dog(?!cat)","g");
var text = "catdogcat catdogdog catdogdogcat".replace(regex,"000");
console.log(text);
Run Code Online (Sandbox Code Playgroud)
它输出了这个:
catdogcat cat000000 cat000dogcat
Run Code Online (Sandbox Code Playgroud)
但我虽然应该输出这个:
catdogcat cat000000 cat000000cat
Run Code Online (Sandbox Code Playgroud)
为什么第二只"狗"不会catdogdogcat被取代000?
编辑:只要两只猫没有猫,我想替换"狗".在catdogdogcat,两只狗满足这个要求,所以他们应该被替换.显然我不明白这些消极的看法......
您的方法存在两个问题.
(?!cat),引擎会检查接下来的三个字符是否cat然后重置到它开始的位置(这就是它向前看的样子),然后您尝试匹配dog这三个字符.因此,前瞻不会添加任何东西:如果你可以匹配dog你显然无法cat在同一位置匹配.你想要的是一个lookbehind (?<!cat),它检查前面的字符是不是cat.不幸的是,JavaScript不支持lookbehind.cat在任一端)需要满足.但你真的想要或那个.如果支持看起来像是看起来像(?<!cat)dog|dog(?!cat)(看起来交替将整个模式分开).但正如我所说,不支持lookbehinds.你似乎在你的第catdogdog一位有*OR*ed两个外观的原因是前面cat没有被检查(参见第1点).那么如何解决看守?Kolink的回答表明(?!cat)...dog,它将看起来放在一个cat开始的位置,并使用前瞻.这有两个新问题:它不能匹配dog字符串的开头(因为前面的三个字符是必需的.它不能匹配两个连续的dogs因为匹配不能重叠(匹配第一个后dog,引擎需要三个新字符,...,dog在实际匹配之前会消耗下一个dog).
有时候你可以通过反转模式和字符串来解决它,从而将外观变成一个前瞻 - 但在你的情况下,这将把最后的前瞻变成一个后视.
我们必须更聪明一点.由于匹配不能重叠,我们可以尝试catdogcat显式匹配,而不替换它(因此在目标字符串中跳过它们),然后只替换dog我们找到的所有s.我们将这两个案例交替进行,因此它们都在字符串中的每个位置都进行了尝试(catdogcat选项优先,尽管这里并不重要).问题是如何获得条件替换字符串.但是让我们来看看到目前为止我们得到了什么:
text.replace(/(catdog)(?=cat)|dog/g, "$1[or 000 if $1 didn't match]")
Run Code Online (Sandbox Code Playgroud)
因此,在第一个替代方案中,我们匹配a catdog并将其捕获到组中1并检查是否存在另一个cat跟随者.在替换字符串中,我们只需写$1回.美丽的是,如果第二种选择匹配,第一组将是未使用的,因此是一个空字符串替换.我们只匹配catdog并使用前瞻而不是立即匹配的catdogcat原因再次是重叠匹配.如果我们使用了catdogcat,那么在输入中catdogcatdogcat,第一个匹配将消耗所有内容,直到并包括第二个匹配cat,因此第二个匹配项dog无法识别第二个匹配项.
现在唯一的问题是,000如果我们使用第二种选择,我们如何进入替代品.
不幸的是,我们无法想象不属于输入字符串的条件替换.诀窍是000在输入字符串的末尾添加一个,如果我们找到一个dog,则在前瞻中捕获,然后再写回:
text.replace(/$/, "000")
.replace(/(catdog)(?=cat)|dog(?=.*(000))/g, "$1$2")
.replace(/000$/, "")
Run Code Online (Sandbox Code Playgroud)
第一个替换添加000到字符串的末尾.
第二个替换匹配catdog(检查另一个cat跟随)并将其捕获到组1(2留空)或匹配dog并捕获000到组2(将组1留空).然后我们$1$2回写,这将是朴素的catdog或000.
第三个替换000在字符串的末尾摆脱了我们无关紧要的东西.
如果你不是准备正则表达式的粉丝,也不是第二个选项中的前瞻,你可以使用一个稍微简单的正则表达式和替换回调:
text.replace(/(catdog)(?=cat)|dog/g, function(match, firstGroup) {
return firstGroup ? firstGroup : "000"
})
Run Code Online (Sandbox Code Playgroud)
随着replace为每个匹配调用所提供函数的版本,其返回值用作替换字符串.函数第一个参数是整个匹配,第二个参数是第一个捕获组(undefined如果组没有参与匹配,将会是这样),依此类推......
所以在替换回调中,我们可以自由地想出我们的000if firstGroup是未定义的(即dog匹配的选项),或者只返回firstGroup它是否存在(即catdogcat匹配的选项).这有点简洁,可能更容易理解.但是,调用该函数的开销会使它显着变慢(尽管这是否重要取决于您想要执行此操作的频率).选择你最喜欢的!
| 归档时间: |
|
| 查看次数: |
395 次 |
| 最近记录: |