Javascript:负面lookbehind等效?

有没有一种方法来实现JavaScript正则expression式中的消极lookbehind ? 我需要匹配一个string不是以一组特定的字符开始的。

看来我无法find一个正则expression式,如果在string的开头find匹配的部分,不会失败。 负面的反向似乎是唯一的答案,但JavaScript没有。

编辑:这是我想工作的正则expression式,但它不:

(?<!([abcdefg]))m

所以它会匹配'jim'或'm'中的'm',而不是'jam'

使用

 newString = string.replace(/([abcdefg])?m/, function($0,$1){ return $1?$0:'m';}); 

由于Javascript支持负向预测 ,所以一个安全的方法是:

假设你想要这样做

 (?<!([abcdefg]))m 
  1. 反转string以匹配
  2. 使用向前的方式应用你的模式“逆向”(注意前方内部的反转匹配expression式,在这种情况下,它保持不变)

     m(?!([abcdefg])) 
  3. 反转所有匹配的标记

例子:

我定义了以下function:

 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:

继安德鲁 – 艾斯利的问题之后,

 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: Ø 

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 

下面是一个例子,其目标是匹配一个double-l,但如果前面是“ba”,则不会。 请注意“balll”这个词 – 真正的逆转应该是压制了前两个,但是与第二个匹配。 但是,通过匹配前两个匹配,然后忽略该匹配作为误报,则正则expression式引擎从该匹配结束进行,并忽略误报内的任何字符。

假设你想要find所有的int而不是前面的unsigned

支持消极的后顾之忧:

 (?<!unsigned )int 

没有支持消极的后顾之忧:

 ((?!unsigned ).{9}|^.{0,8})int 

基本的想法是抓取n个前面的字符,排除负向前瞻的匹配,但也匹配没有前n个字符的情况。 (其中n是后顾长度)。

所以正确的正则expression式:

 (?<!([abcdefg]))m 

将转化为:

 ((?!([abcdefg])).|^)m 

您可能需要使用捕获组来查找感兴趣的string的确切位置,或者您想用其他方法replace特定部分。

你可以通过否定字符集来定义一个非捕获组:

 (?:[^ag])m 

…这将匹配每个没有任何这些字母前面的m

遵循Mijoja的想法,并从JasonS揭露的问题中得出这个想法。 我检查了一下,但不知道我自己,所以比js正则expression式更专家的validation将是伟大的:)

 var re = /(?=(..|^.?)(ll))/g // matches empty string position // whenever this position is followed by // a string of length equal or inferior (in case of "^") // to "lookbehind" value // + actual value we would want to match , str = "Fall ball bill balll llama" , str_done = str , len_difference = 0 , doer = function (where_in_str, to_replace) { str_done = str_done.slice(0, where_in_str + len_difference) + "[match]" + str_done.slice(where_in_str + len_difference + to_replace.length) len_difference = str_done.length - str.length /* if str smaller: len_difference will be positive else will be negative */ } /* the actual function that would do whatever we want to do with the matches; this above is only an example from Jason's */ /* function input of .replace(), only there to test the value of $behind and if negative, call doer() with interesting parameters */ , checker = function ($match, $behind, $after, $where, $str) { if ($behind !== "ba") doer ( $where + $behind.length , $after /* one will choose the interesting arguments to give to the doer, it's only an example */ ) return $match // empty string anyhow, but well } str.replace(re, checker) console.log(str_done) 

我的个人输出:

 Fa[match] ball bi[match] bal[match] [match]ama 

原则是在任何两个字符之间的string中的每个点上调用checker ,只要该位置是以下位置的起点:

—任何不想要的大小的任何子string(这里是'ba' ,因此.. )(如果这个大小是已知的,否则它可能更难)

— —如果它是string的开头,那么比它更小: ^.?

在此之后,

—什么是实际寻找(这里'll' )。

在每次调用checker ,都会有一个testing来检查ll之前的值是不是我们不想要的( !== 'ba' ); 如果是这样的话,我们调用另一个函数,并且它将必须是这个( doer ),它将在str上进行更改,如果目的是这个,或者更一般地,将会input必要的数据来手动处理str的扫描结果。

在这里我们改变了string,所以我们需要保留一段长度的差异,以便抵消replace给定的位置,所有这些都是在str计算的,而str本身从不改变。

由于原始string是不可变的,所以我们可以使用variablesstr来存储整个操作的结果,但是我认为已经被更换复杂化的例子会更清晰地与另一个variables( str_done )相关联。

我认为在表演方面,它必须是相当苛刻的:所有那些毫无意义的replace成'', this str.length-1倍,再加上这里手工更换doer,这意味着很多切片…可能在这个特定的上面的情况,可以通过将string切割成一个一圈的forms,在我们想要插入[match].join()[match]本身。

另一件事是,我不知道它将如何处理更复杂的情况,也就是说,复杂的价值观的虚假lookbehind …长度可能是最有问题的数据得到。

并且在checker ,如果$后面有多个可能的不需要的值,我们将不得不对另一个正则expression式进行一个testing(在caching(创build)外部checker是最好的,以避免相同的正则expression式对象每次打电话给checker时都会被创build出来)来知道是否我们试图避免。

希望我已经清楚了; 如果不是不犹豫,我会更好的尝试。 🙂

这有效地做到了

 "jim".match(/[^ag]m/) > ["im"] "jam".match(/[^ag]m/) > null 

search并replace示例

 "jim jam".replace(/([^ag])m/g, "$1M") > "jiM jam" 

请注意负面的后视string必须是1个字符长这个工作。

/(?![abcdefg])[^abcdefg]m/gi是这是一个技巧。

这可能会有所帮助,具体取决于上下文:

这匹配在吉姆m,但不是果酱:

 "jim jam".replace(/[ag]m/g, "").match(/m/g) 
Interesting Posts