有没有办法在 JavaScript 正则表达式中实现负向后视?我需要匹配一个不以特定字符集开头的字符串。
如果在字符串的开头找到匹配的部分,我似乎无法找到执行此操作的正则表达式而不会失败。否定的lookbehinds似乎是唯一的答案,但JavaScript没有。
这是我想要使用的正则表达式,但它没有:
(?<!([abcdefg]))m
所以它会匹配“jim”或“m”中的“m”,但不匹配“jam”
有没有办法在 JavaScript 正则表达式中实现负向后视?我需要匹配一个不以特定字符集开头的字符串。
如果在字符串的开头找到匹配的部分,我似乎无法找到执行此操作的正则表达式而不会失败。否定的lookbehinds似乎是唯一的答案,但JavaScript没有。
这是我想要使用的正则表达式,但它没有:
(?<!([abcdefg]))m
所以它会匹配“jim”或“m”中的“m”,但不匹配“jam”
自 2018 年以来,Lookbehind Assertions成为ECMAScript 语言规范的一部分。
// positive lookbehind
(?<=...)
// negative lookbehind
(?<!...)
2018 年之前的回答
由于 Javascript 支持负前瞻,一种方法是:
反转输入字符串
与反向正则表达式匹配
反转并重新格式化匹配项
const reverse = s => s.split('').reverse().join('');
const test = (stringToTests, reversedRegexp) => stringToTests
.map(reverse)
.forEach((s,i) => {
const match = reversedRegexp.test(s);
console.log(stringToTests[i], match, 'token:', match ? reverse(reversedRegexp.exec(s)[0]) : 'Ø');
});
示例 1:
按照@andrew-ensley 的问题:
test(['jim', 'm', 'jam'], /m(?!([abcdefg]))/)
输出:
jim true token: m
m true token: m
jam false token: Ø
示例 2:
遵循@neaumusic 评论(匹配max-height
但不匹配line-height
,标记为height
):
test(['max-height', 'line-height'], /thgieh(?!(-enil))/)
输出:
max-height true token: height
line-height false token: Ø
后向断言得到了接受入ECMAScript规范在2018年。
正向后视用法:
console.log(
"$9.99 €8.47".match(/(?<=\$)\d+\.\d*/) // Matches "9.99"
);
负面回顾用法:
console.log(
"$9.99 €8.47".match(/(?<!\$)\d+\.\d*/) // Matches "8.47"
);
平台支持:
假设您想查找所有int
不以 开头的内容unsigned
:
支持负向后视:
(?<!unsigned )int
不支持负向后视:
((?!unsigned ).{9}|^.{0,8})int
基本上的想法是抓取 n 个前面的字符并排除带有否定前瞻的匹配,但也匹配没有前面 n 个字符的情况。(其中 n 是后视的长度)。
所以有问题的正则表达式:
(?<!([abcdefg]))m
会翻译成:
((?!([abcdefg])).|^)m
您可能需要使用捕获组来找到您感兴趣的字符串的确切位置,或者您想用其他东西替换特定部分。
Mijoja 的策略适用于您的特定情况,但不适用于一般情况:
js>newString = "Fall ball bill balll llama".replace(/(ba)?ll/g,
function($0,$1){ return $1?$0:"[match]";});
Fa[match] ball bi[match] balll [match]ama
这是一个示例,其中目标是匹配双 l 但如果它前面是“ba”,则不是。请注意单词“ballll”——真正的后视应该抑制前 2 个 l 但匹配第二对。但是通过匹配前 2 个 l 然后忽略该匹配作为误报,正则表达式引擎从该匹配的末尾继续进行,并忽略误报中的任何字符。
用
newString = string.replace(/([abcdefg])?m/, function($0,$1){ return $1?$0:'m';});