为什么这个正则表达式返回匹配?

时间:2015-02-12 21:11:08

标签: javascript node.js

http://jsfiddle.net/sqee98xr/

var reg = /^(?!managed).+\.coffee$/
var match = '20150212214712-test-managed.coffee'.match(reg)
console.log(match) // prints '20150212214712-test-managed.coffee'

我想匹配正则表达式只有在没有单词"#34;#34;以字符串形式出现 - 我该怎么做?

2 个答案:

答案 0 :(得分:1)

否定的前瞻是奇怪的。你必须匹配的不仅仅是你想要的单词。我知道这很奇怪。

var reg = /^(?!.*managed).+\.coffee$/

http://jsfiddle.net/sqee98xr/3/

编辑:看起来我真的被一些人的皮肤所困扰了#34;奇怪的"描述符和布局描述。这很奇怪,因为在表面层面上,术语是“负向前瞻”。暗示"向前看并确保这些括号中的内容不在那里,然后返回并继续匹配" 。作为正则表达式的爱好者,我仍然宣称这个命名很奇怪,特别是对于第一次断言的用户。对我而言,更容易将其视为"而不是"操作员,而不是实际向前爬行的东西,"展望未来"。为了使行为类似于实际的"向前看",您必须匹配搜索词之前的所有内容,因此.*

更简单的解决方案是删除字符串开头(^)断言。同样,对我来说,更容易阅读?!,因为"不是"。

var reg = /(?!managed).+\.coffee$/

答案 1 :(得分:1)

虽然 @RyanWheale 的解决方案是正确的,但解释并不正确。原因在于,包含单词" managed" (例如" test-managed" )的字符串可以计为 "托管" 。要先了解这一点,请查看正则表达式:

/^(?!managed).+\.coffee$/ 

// (Not "managed")(one or more characters)(".")("coffee")

首先,我们不能使用文本" managed",然后我们可以有一个或多个字符,然后是一个点,然后是文本" coffee"。这是一个满足这一要求的例子。

  

" Hello.coffee" [通过]

有道理,"Hello"肯定不是"managed"。这是另一个从您的字符串开始的示例:

  

" 20150212214712-test-managed.coffee" [通过]

为什么呢?因为" 20150212214712-test-managed" 不是字符串"托管" 即使它包含字符串,计算机也不会知道你的意思。它认为" 20150212214712-test-managed" 是一个字符串,不会以相同的方式管理" " andflaksfj" 不是"托管" 。因此,失败的唯一方法是"托管" 位于字符串的开头:

  

" managed.coffee" [失败]

这不仅仅是因为文本"托管" 就在那里。说电脑说"managed."不是"managed"。它确实会传递(?!managed)部分,但字符串的其余部分只是coffee而且会因为没有"."而失败。

最后,对此的解决方案是另一个答案的建议:

/^(?!.*managed).+\.coffee$/

现在字符串" 20150212214712-test-managed.coffee" 失败了,因为无论它如何看待:" test-managed& #34; " - 管理" " st-managed" 等。仍然算作{ {1}}并失败。如上面的示例所示,它可以尝试从(?!.*managed)添加子字符串,但正如所解释的那样,这将导致字符串在正则表达式的其余部分(".coffee")中失败。

希望这个冗长的解释解释说,负面展望并不奇怪,只是非常按字面意思提出要求。