我想匹配所有以“.htm”结尾的字符串,除非它以“foo.htm”结尾。我通常对正则表达式很满意,但消极的前瞻让我很难过。为什么这不起作用?
/(?!foo)\.htm$/i.test("/foo.htm"); // returns true. I want false.
我应该改用什么?我认为我需要一个“消极的看法”表达(如果 JavaScript支持这样的事情,我知道它不支持)。
我想匹配所有以“.htm”结尾的字符串,除非它以“foo.htm”结尾。我通常对正则表达式很满意,但消极的前瞻让我很难过。为什么这不起作用?
/(?!foo)\.htm$/i.test("/foo.htm"); // returns true. I want false.
我应该改用什么?我认为我需要一个“消极的看法”表达(如果 JavaScript支持这样的事情,我知道它不支持)。
这个问题真的很简单。这将做到:
/^(?!.*foo\.htm$).*\.htm$/i
您所描述的(您的意图)是负面的后视,而 Javascript 不支持后视。
Look-aheads 从放置它们的角色向前看——并且您已将其放置在.
. 因此,您实际上是在说“.htm
只要从该位置 ( .ht
) 开始的前三个字符不是以结尾的任何内容foo
”,这始终是正确的。
通常,消极的后视的替代品是匹配比你需要的更多,并且只提取你真正需要的部分。这很 hacky,根据你的具体情况,你可能会想出别的东西,但是像这样:
// Checks that the last 3 characters before the dot are not foo:
/(?!foo).{3}\.htm$/i.test("/foo.htm"); // returns false
如前所述,JavaScript 不支持否定的后向断言。
但是您可以使用一种解决方法:
/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";
这将匹配以 结尾的所有内容,但如果匹配,.htm
它将存储"foo"
到中,因此您可以单独处理它。RegExp.$1
foo.htm
就像 Renesis 提到的,JavaScript 不支持“lookbehind”,所以也许只需组合使用两个正则表达式:
!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)
String.prototype.endsWith ( ES6 )
console.log( /* !(not)endsWith */
!"foo.html".endsWith("foo.htm"), // true
!"barfoo.htm".endsWith("foo.htm"), // false (here you go)
!"foo.htm".endsWith("foo.htm"), // false (here you go)
!"test.html".endsWith("foo.htm"), // true
!"test.htm".endsWith("foo.htm") // true
);
可能这个答案比必要的时间晚了一点,但我会把它留在这里,以防有人现在遇到同样的问题(问这个问题后 7 年零 6 个月)。
Now lookbehinds are included in ECMA2018 standard & supported at least in last version of Chrome. However, you might solve the puzzle with or without them.
A solution with negative lookahead:
let testString = `html.htm app.htm foo.tm foo.htm bar.js 1to3.htm _.js _.htm`;
testString.match(/\b(?!foo)[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
A solution with negative lookbehind:
testString.match(/\b[\w-.]+(?<!foo)\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
A solution with (technically) positive lookahead:
testString.match(/\b(?=[^f])[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]
etc.
All these RegExps tell JS engine the same thing in different ways, the message that they pass to JS engine is something like the following.
Please, find in this string all sequences of characters that are:
您可以使用类似的东西来模拟负面的后视
/(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/
,但程序化方法会更好。