Ответ 1
Проблема довольно проста. Это сделает это:
/^(?!.*foo\.htm$).*\.htm$/i
Я хочу, чтобы все строки заканчивались на ".htm", если они не заканчиваются на "foo.htm". Я вообще порядочный с регулярными выражениями, но негативные взгляды меня озадачат. Почему это не работает?
/(?!foo)\.htm$/i.test("/foo.htm"); // returns true. I want false.
Что я должен использовать вместо этого? Я думаю, что мне нужно выражение "negative look behind" (если JavaScript поддерживает такую вещь, о которой я знаю, это не так).
Проблема довольно проста. Это сделает это:
/^(?!.*foo\.htm$).*\.htm$/i
То, что вы описываете (ваше намерение), является негативным взглядом, а Javascript не поддерживает обратную связь.
Взгляд вперед - смотреть на персонажа, на котором они размещены -— и вы разместили его до .
. Итак, что вы на самом деле говорите "что-либо, заканчивающееся на .htm
, если первые три символа, начинающиеся с этой позиции (.ht
), не являются foo
", что всегда верно.
Обычно замена отрицательных обратных задержек должна соответствовать большему, чем вам нужно, и извлекать только ту часть, которая вам действительно нужна. Это хаки, и в зависимости от вашей точной ситуации вы, вероятно, можете придумать что-то еще, но что-то вроде этого:
// Checks that the last 3 characters before the dot are not foo:
/(?!foo).{3}\.htm$/i.test("/foo.htm"); // returns false
Как уже упоминалось, JavaScript не поддерживает отрицательные утверждения в обратном порядке.
Но вы можете использовать workaroud:
/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";
Это будет соответствовать всем, что заканчивается на .htm
, но оно сохранит "foo"
в RegExp.$1
, если оно соответствует foo.htm
, поэтому вы можете обрабатывать его отдельно.
Как упоминается Renesis, "lookbehind" не поддерживается в JavaScript, поэтому, возможно, просто используйте два регулярных выражения в комбинации:
!/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
);
Вы можете подражать негативному lookbehind с чем-то вроде
/(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/
, но программный подход будет лучше.