我想匹配所有以“.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 不支持后视。
前瞻从它们所在的字符向前看——你已经把它放在.
. 因此,您实际上是在说“.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
);