Javascript:负面的lookbehind相当于?

And*_*ley 133 javascript regex negative-lookbehind

有没有办法在javascript正则表达式中实现相当于负面的lookbehind?我需要匹配一个不以特定字符集开头的字符串.

如果在字符串的开头找到匹配的部分,我似乎无法找到正确执行此操作的正则表达式.负面的看起来似乎是唯一的答案,但javascript没有.

编辑:这是我想要工作的正则表达式,但它没有:

(?<!([abcdefg]))m

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

JBE*_*JBE 81

由于Javascript支持负前瞻,一种方法是:

  1. 反转输入字符串

  2. 与反向正则表达式匹配

  3. 反转并重新格式化比赛


// positive lookbehind
(?<=...)
// negative lookbehind
(?<!...)
Run Code Online (Sandbox Code Playgroud)

例1:

关注@ andrew-ensley的问题:

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]) : 'Ø');
  });
Run Code Online (Sandbox Code Playgroud)

输出:

test(['jim', 'm', 'jam'], /m(?!([abcdefg]))/)
Run Code Online (Sandbox Code Playgroud)

例2:

关注@neaumusic评论(匹配max-height但不是line-height,令牌是height):

jim true token: m
m true token: m
jam false token: Ø
Run Code Online (Sandbox Code Playgroud)

输出:

test(['max-height', 'line-height'], /thgieh(?!(-enil))/)
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的问题在于,当你有前瞻和后瞻时,它不起作用 (33认同)
  • 你能否展示一个工作实例,说我想匹配`max-height`而不是`line-height`我只希望匹配为`height` (3认同)

Kam*_*zot 56

我们假设你想找到所有int没有前面的unsigned:

支持负面观察:

(?<!unsigned )int
Run Code Online (Sandbox Code Playgroud)

不支持负面观察:

((?!unsigned ).{9}|^.{0,8})int
Run Code Online (Sandbox Code Playgroud)

基本上,想法是抓住前面的n个字符并排除与负前瞻的匹配,但也匹配没有前n个字符的情况.(其中n是后视的长度).

所以有问题的正则表达式:

(?<!([abcdefg]))m
Run Code Online (Sandbox Code Playgroud)

会转化为:

((?!([abcdefg])).|^)m
Run Code Online (Sandbox Code Playgroud)

您可能需要使用捕获组来查找您感兴趣的字符串的确切位置,或者您希望用其他内容替换特定部分.

  • 这应该是正确的答案.请参阅:"所以它会匹配'jim'或'm'中的'm',但不匹配'jam'".replace(/(j(?!([abcdefg])).| ^)m/g, "$ 1 [MATCH]")`返回`"所以它匹配'ji [MATCH]'或'm'中的'm',但不匹配'jam'"`这很简单,它有效! (2认同)

Okk*_*kku 44

后向断言得到了接受ECMAScript规范在2018年这已得到落实V8没有与谷歌浏览V62标志运Node.js的V6标志和V9的背后没有一个标志.因此,如果您正在开发仅限Chrome的环境(例如Electron)或Node,您可以立即开始使用lookbehinds!

积极的背后使用:

console.log(
  "$9.99  €8.47".match(/(?<=\$)\d+(\.\d*)?/) // Matches "9.99"
);
Run Code Online (Sandbox Code Playgroud)

消极的背后使用:

console.log(
  "$9.99  €8.47".match(/(?<!\$)\d+(?:\.\d*)/) // Matches "8.47"
);
Run Code Online (Sandbox Code Playgroud)

支持其他平台:

  • 有没有保鲜纸? (2认同)

Jas*_*n S 41

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
Run Code Online (Sandbox Code Playgroud)

这是一个例子,其目标是匹配double-l,但不是如果它前面是"ba".注意单词"balll" - 真正的lookbehind应该抑制前2个,但匹配第2对.但是通过匹配前2个,然后将该匹配忽略为误报,正则表达式引擎从该匹配结束开始,并忽略误报内的任何字符.

  • 啊,你是对的.然而,这比我以前更接近.我可以接受这个,直到有更好的东西出现(比如javascript实际上实现了lookbehinds). (5认同)

Mij*_*oja 33

使用

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

  • @bug.不做任何事情的演示是一种奇怪的演示.答案就是好像它只是复制和粘贴,而不了解它是如何工作的.因此缺乏相应的解释和未能证明任何事情已经匹配. (56认同)
  • 这没有做任何事:`newString`总是等于`string`.为什么这么多人投票? (10认同)
  • 这个概念是正确的,但是是的,它并没有很好地演示.尝试在JS控制台中运行它......""Jim Jam Momm m".replace(/([abcdefg])?m/g,function($ 0,$ 1){return $ 1?$ 0:'[match]';} );`.它应该返回`Ji [match] Jam Mo [match] [match] [match]`.但同时请注意,正如Jason在下面提到的,它可能会在某些边缘情况下失败. (7认同)
  • @MikeM:SO的规则是,如果它回答“书面”问题,那是正确的。OP未指定用例 (2认同)

Kle*_*vič 9

您可以通过否定您的字符集来定义非捕获组:

(?:[^a-g])m
Run Code Online (Sandbox Code Playgroud)

...将匹配任何这些字母前面的每个m NOT.

  • 这是真的.一个角色类代表......一个角色!您的所有非捕获组正在执行的操作不是在替换上下文中使该值可用.你的表达并不是说"每个m之前都没有任何这些字母",它说的是"每个m*前面都有一个字符*不是那些字母中的任何一个" (4认同)
  • 对于也解决原始问题(字符串的开头)的答案,它还必须包含一个选项,因此得到的正则表达式将是`(?:[^ ag] | ^)m`.有关运行示例,请参阅https://regex101.com/r/jL1iW6/2. (4认同)
  • 我认为这场比赛实际上也涵盖了前面的角色. (2认同)