这是一个在大多数正则表达式实现中都可以正常工作的正则表达式:

(?<!filename)\.js$


这与.js匹配以.js结尾的字符串,但filename.js除外(

JavaScript没有后面的正则表达式。有没有人能拼凑出一个可达到相同结果并可以在javascript中工作的替代正则表达式?

这里有一些想法,但需要辅助函数。我希望使用正则表达式来实现它:
http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript

评论

如果只需要检查特定的文件名或文件名列表,为什么不只使用两次检查呢?检查它是否以.js结尾,然后检查是否与filename.js不匹配,反之亦然。

更新:最新的公共Chrome版本(v62)开箱即用地包含了lookbehinds:D但请注意,lookbehinds仍处于提议阶段3:github.com/tc39/proposal-regexp-lookbehind。因此,可能需要一段时间才能到处都支持JavaScript。最好在生产中使用时要小心!

#更新:ES2018包括后置断言加上:-dotAll模式(s标志)-后置断言-命名捕获组-Unicode属性转义

只需将(?<= thingy)thingy用于正向后视,而(?<!thingy)thingy用于负向后视。现在它支持它们。

@ K._截至2018年2月,这还不是真的!!而且这将需要一些时间,因为浏览器和引擎必须实现该规范(草案中为最新版本)。

#1 楼

^(?!filename).+\.js对我有效

经过了以下测试:


test.js匹配filename.js没有匹配

可以在正则表达式中找到此正则表达式的正确说明,以匹配不包含单词的字符串?

自JavaScript 1.5版开始提供向前看,并且受所有主要浏览器支持

已更新,以匹配filename2.js和2filename.js,但不匹配filename.js

(^(?!filename\.js$).).+\.js

评论


您链接到的那个问题谈论的是一个稍微不同的问题:匹配一个在任何地方都不包含目标词的字符串。这很简单:匹配一个不以目标词开头的字符串。

–艾伦·摩尔
2011年9月11日下午5:50

那真的很好,它只漏掉了诸如filename2.js或filenameddk.js之类的情况。这是没有比赛,但应该是比赛。

–丹尼尔
2011年9月11日7:18



@daniel您要求进行回溯,而不是提前回溯,您为什么接受此答案?

– hek2mgl
15年5月28日在8:56



给定的一个与a.js不匹配

–inetphantom
16-3-17在12:35



带有lookbehind的原始正则表达式与2filename.js不匹配,但此处给出的正则表达式匹配。更加合适的是^(?!。* filename \ .js $)。* \。js $。这意味着匹配* filename.js以外的任何* .js。

– weibeld
17年5月16日在5:16



#2 楼

编辑:从ECMAScript 2018起,本地支持向后断言(甚至无边界)。

在以前的版本中,您可以执行以下操作:

^(?:(?!filename\.js$).)*\.js$


这将明确地执行lookbehind表达式的隐式操作:检查字符串中的每个字符,如果lookbehind表达式加上后的正则表达式不匹配,则仅允许该字符匹配。

^                 # Start of string
(?:               # Try to match the following:
 (?!              # First assert that we can't match the following:
  filename\.js    # filename.js 
  $               # and end-of-string
 )                # End of negative lookahead
 .                # Match any character
)*                # Repeat as needed
\.js              # Match .js
$                 # End of string


另一种编辑:

我很难说(特别是因为这个答案已经被广泛接受),有一种容易得多的方法可以实现这个目标。无需检查每个字符的前瞻性:

^(?!.*filename\.js$).*\.js$


也可以正常工作:

^                 # Start of string
(?!               # Assert that we can't match the following:
 .*               # any string, 
  filename\.js    # followed by filename.js
  $               # and end-of-string
)                 # End of negative lookahead
.*                # Match any string
\.js              # Match .js
$                 # End of string


评论


适用于许多情况,但前面没有字符,例如:filename.js(works-nomatch)filename2.js(works-match)blah.js(works-match)2filename.js(不起作用-nomatch) ---话虽这么说,但后面的限制具有直到现在我都没有意识到的相同限制...

–丹尼尔
2011-09-11 7:40



@daniel:嗯,您的正则表达式(带有后向)也与2filename.js不匹配。我的正则表达式在与示例正则表达式完全相同的情况下匹配。

–蒂姆·皮茨克(Tim Pietzcker)
2011年9月11日17:51

原谅我的天真,但这里的非俘虏团体有用吗?我一直都知道这仅在尝试收集回字符串替换中的引用时才有用。据我所知,这也将起作用^(?! filename \ .js $)。* \。js $

–我想要答案
17 Mar 28 '17 6:46



不完全是,该正则表达式仅在字符串的开头检查“ filename.js”。但是^(?!。* filename \ .js $)。* \。js $可以工作。尝试考虑可能仍然需要ncgroup的情况...

–蒂姆·皮茨克(Tim Pietzcker)
17年3月28日在6:53

这种方法可以概括为:而不是在X后面看,而是在X之前看每个字符?

– ar鼠
18年6月29日在7:27

#3 楼

假设您要查找所有不以int开头的unsigned

支持负向后看:

(?<!unsigned )int


不支持负向后向查找:

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


基本思想是获取n个前面的字符并排除否定的匹配,但也要匹配不包含n个字符的情况。 (其中n是向后看的长度)。

正则表达式中的正则表达式:

(?<!filename)\.js$


将转换为:

((?!filename).{8}|^.{0,7})\.js$


您可能需要与捕获组一起使用,才能找到您感兴趣的字符串的确切位置,或者您不想用其他东西替换特定部分。

评论


我刚刚将其转换为:(?<!barna)(?<!ene)(?<!en)(?<!erne)(?:sin |vår)e?(?:$ |(?!egen | egne) )到(?!barna)。(?! erne)。(?! ene)。(?! en)..(?:sin |vår)e?(?:$ |(?!egen | egne))其中满足我的需要只是将其作为另一个“现实世界”场景提供。见链接

–艾里克·伯克兰(Eirik Birkeland)
16 Mar 16 '16 at 13:23

我认为您的意思是:((?!unsigned)。{9} | ^。{0,8})

– Pansay
17-2-4在10:07



@pansay是的。谢谢。我只是纠正了我的回答。

–卡米尔·索特(Kamil Szot)
17年2月13日在20:32

感谢您提供更通用的答案,即使在文本中需要进行深度匹配的情况下,该答案也可以使用(在此处最初的^不切实际)!

–米洛斯·姆多维奇(Milos Mrdovic)
17年8月17日在9:28

#4 楼

如果可以向前看但可以向后看,则可以先反转字符串,然后再进行前瞻。当然,还需要做更多的工作。

评论


这个答案确实可以使用一些改进。在我看来,这更像是一则评论。

– mickmackusa
18年4月26日在6:31

#5 楼

这是Tim Pietzcker答案的等效解决方案(另请参见相同答案的注释):

^(?!.*filename\.js$).*\.js$


表示匹配*.js,但*filename.js除外。

要获得此解决方案,您可以检查负向后看排除了哪些模式,然后使用负向前瞻来完全排除这些模式。

#6 楼

下面是一个正面的JavaScript替代方法,它显示了如何捕获以“ Michael”作为姓氏的人的姓氏。

1)给定此文本:

const exampleText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";


获取姓迈克尔的姓氏的数组。
结果应该是:["Jordan","Johnson","Green","Wood"]

2)解决方案:

function getMichaelLastName2(text) {
  return text
    .match(/(?:Michael )([A-Z][a-z]+)/g)
    .map(person => person.slice(person.indexOf(' ')+1));
}

// or even
    .map(person => person.slice(8)); // since we know the length of "Michael "


3)检查解决方案

console.log(JSON.stringify(    getMichaelLastName(exampleText)    ));
// ["Jordan","Johnson","Green","Wood"]


此处演示:http://codepen.io/PiotrBerebecki/pen/GjwRoo


您也可以通过运行以下代码段尝试一下。




 const inputText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";



function getMichaelLastName(text) {
  return text
    .match(/(?:Michael )([A-Z][a-z]+)/g)
    .map(person => person.slice(8));
}

console.log(JSON.stringify(    getMichaelLastName(inputText)    ));