有没有办法在javascript正则表达式中实现相当于负面的lookbehind?我需要匹配一个不以特定字符集开头的字符串.
如果在字符串的开头找到匹配的部分,我似乎无法找到正确执行此操作的正则表达式.负面的看起来似乎是唯一的答案,但javascript没有.
编辑:这是我想要工作的正则表达式,但它没有:
(?
所以它会匹配'jim'或'm'中的'm',但不会匹配'jam'
由于Javascript支持负前瞻,一种方法是:
反转输入字符串
与反向正则表达式匹配
反转并重新格式化比赛
// positive lookbehind
(?<=...)
// negative lookbehind
(?
例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]) : 'Ø');
});
输出:
test(['jim', 'm', 'jam'], /m(?!([abcdefg]))/)
例2:
关注@neaumusic评论(匹配max-height
但不是line-height
,令牌是height
):
jim true token: m
m true token: m
jam false token: Ø
输出:
test(['max-height', 'line-height'], /thgieh(?!(-enil))/)
这种方法的问题在于,当你有前瞻和后瞻时,它不起作用
你能否展示一个工作实例,说我想匹配`max-height`而不是`line-height`我只希望匹配为`height`
2> Kamil Szot..:
我们假设你想找到所有int
没有前面的unsigned
:
支持负面观察:
(?
不支持负面观察:
((?!unsigned ).{9}|^.{0,8})int
基本上,想法是抓住前面的n个字符并排除与负前瞻的匹配,但也匹配没有前n个字符的情况.(其中n是后视的长度).
所以有问题的正则表达式:
(?
会转化为:
((?!([abcdefg])).|^)m
您可能需要使用捕获组来查找您感兴趣的字符串的确切位置,或者您希望用其他内容替换特定部分.
这应该是正确的答案.请参阅:"所以它会匹配'jim'或'm'中的'm',但不匹配'jam'".replace(/(j(?!([abcdefg])).| ^)m/g, "$ 1 [MATCH]")`返回`"所以它匹配'ji [MATCH]'或'm'中的'm',但不匹配'jam'"`这很简单,它有效!
3> Okku..:
后向断言得到了接受入ECMAScript规范在2018年这已得到落实V8并没有与谷歌浏览V62标志运和Node.js的V6标志和V9的背后没有一个标志.因此,如果您正在开发仅限Chrome的环境(例如Electron)或Node,您可以立即开始使用lookbehinds!
积极的背后使用:
console.log(
"$9.99 €8.47".match(/(?<=\$)\d+(\.\d*)?/) // Matches "9.99"
);
4> Jason S..:
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" - 真正的lookbehind应该抑制前2个,但匹配第2对.但是通过匹配前2个,然后将该匹配忽略为误报,正则表达式引擎从该匹配结束开始,并忽略误报内的任何字符.
啊,你是对的.然而,这比我以前更接近.我可以接受这个,直到有更好的东西出现(比如javascript实际上实现了lookbehinds).
5> Mijoja..:
使用
newString = string.replace(/([abcdefg])?m/, function($0,$1){ return $1?$0:'m';});
@bug.不做任何事情的演示是一种奇怪的演示.答案就是好像它只是复制和粘贴,而不了解它是如何工作的.因此缺乏相应的解释和未能证明任何事情已经匹配.
这没有做任何事:`newString`总是等于`string`.为什么这么多人投票?
这个概念是正确的,但是是的,它并没有很好地演示.尝试在JS控制台中运行它......""Jim Jam Momm m".replace(/([abcdefg])?m/g,function($ 0,$ 1){return $ 1?$ 0:'[match]';} );`.它应该返回`Ji [match] Jam Mo [match] [match] [match]`.但同时请注意,正如Jason在下面提到的,它可能会在某些边缘情况下失败.
@MikeM:SO的规则是,如果它回答“书面”问题,那是正确的。OP未指定用例
6> Klemen Slavi..:
您可以通过否定您的字符集来定义非捕获组:
(?:[^a-g])m
...将匹配任何这些字母前面的每个m
NOT.
这是真的.一个角色类代表......一个角色!您的所有非捕获组正在执行的操作不是在替换上下文中使该值可用.你的表达并不是说"每个m之前都没有任何这些字母",它说的是"每个m*前面都有一个字符*不是那些字母中的任何一个"
对于也解决原始问题(字符串的开头)的答案,它还必须包含一个选项,因此得到的正则表达式将是`(?:[^ ag] | ^)m`.有关运行示例,请参阅https://regex101.com/r/jL1iW6/2.
我认为这场比赛实际上也涵盖了前面的角色.