javascript正则表达式-寻找替代方案吗?


142

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

(?<!filename)\.js$

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

Javascript没有后面的正则表达式。有谁能放一个替代的正则表达式来达到相同的结果并可以在javascript中工作?

这里有一些想法,但是需要帮助功能。我希望仅通过正则表达式来实现它:http : //blog.stevenlevithan.com/archives/mimic-lookbehind-javascript


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

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

2
#更新:ES2018包括lookbehind 断言 :-dotAll模式(s标志)-Lookbehind断言-命名捕获组-Unicode属性转义
Ashley Coolman

2
只要使用(?<=thingy)thingy积极的回顾后,并(?<!thingy)thingy负回顾后现在它支持他们。
КонстантинВан

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

Answers:


64

^(?!filename).+\.js 为我工作

经过测试:

  • test.js匹配
  • blabla.js比赛
  • filename.js不匹配

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

JavaScript 1.5版开始,可以使用“向前看”功能并且所有主要浏览器都支持“向前看”功能

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

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


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

那真的很好,它只会漏掉诸如filename2.js或filenameddk.js之类的情况。这是不匹配,但应该匹配。
丹尼尔

9
@daniel您要求进行回顾,而不是先行,为什么您接受此答案?
hek2mgl

1
给定的一个不匹配a.js
inetphantom

1
带有lookbehind的原始正则表达式不匹配2filename.js,但此处给出的正则表达式匹配。一个更合适的是^(?!.*filename\.js$).*\.js$。这就是说,匹配*.js 除以外的 任何一个*filename.js
weibeld

152

编辑:从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) ---话说回来,在回顾后有哪些我不知道到现在为止相同的限制...
丹尼尔

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

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

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

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

25

假设您想查找所有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

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

@pansay是的。谢谢。我只是纠正了我的回应。
卡米尔·索尔

2
感谢您提供更通用的答案,该答案即使在文本中需要深度匹配的地方也可以使用(在此处最初的^不切实际)!
米洛斯·姆多维奇

5

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


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

2

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

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

这意味着,*.js除之外,要匹配*filename.js

要获得此解决方案,您可以检查排除在后的否定性模式,然后使用排除性的前瞻性准确排除这些模式。


-1

以下是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?";

获取姓名为Michael的人的姓氏数组。结果应为:["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)    ));

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.