Регулярное выражение отрицательного взгляда - PullRequest
61 голосов
/ 28 июля 2011

Я хочу сопоставить все строки, оканчивающиеся на ".htm", если только он не заканчивается на "foo.htm". Я обычно приличный с регулярными выражениями, но отрицательные взгляды поставили меня в тупик. Почему это не работает?

/(?!foo)\.htm$/i.test("/foo.htm");  // returns true. I want false.

Что я должен использовать вместо этого? Я думаю, что мне нужно выражение «отрицательный взгляд за » (если JavaScript поддерживает такую ​​вещь, а я знаю, что нет).

Ответы [ 7 ]

91 голосов
/ 28 июля 2011

Проблема довольно проста на самом деле.Это сделает это:

/^(?!.*foo\.htm$).*\.htm$/i

18 голосов
/ 28 июля 2011

То, что вы описываете (ваше намерение), является отрицательным оглядкой назад , а 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 
2 голосов
/ 28 июля 2011

Как упоминал Renesis, «lookbehind» не поддерживается в JavaScript, поэтому, возможно, просто используйте два регулярных выражения в комбинации:

!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)
2 голосов
/ 28 июля 2011

Как уже упоминалось, JavaScript не поддерживает отрицательные косвенные утверждения.

Но вы можете использовать workaroud:

/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";

Это будет соответствовать всему, что заканчивается .htm, носохраните "foo" в RegExp.$1, если он соответствует foo.htm, так что вы можете обрабатывать его отдельно.

1 голос
/ 14 февраля 2019

Возможно, этот ответ прибыл немного позже, чем необходимо, но я оставлю его здесь на всякий случай, если кто-то столкнется с той же проблемой сейчас (7 лет, 6 месяцев после того, как этот вопрос был задан).

Теперь взгляды включены в стандарт ECMA2018 и поддерживаются по крайней мере в последней версии Chrome. Однако вы можете решить головоломку с ними или без них.

Решение с отрицательным взглядом:

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"]

Решение с отрицательным взглядом сзади:

testString.match(/\b[\w-.]+(?<!foo)\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]

Решение с (технически) положительным взглядом:

testString.match(/\b(?=[^f])[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]

и т.д.

Все эти регулярные выражения по-разному говорят движку JS об одном и том же: сообщение, которое они передают движку JS, выглядит примерно так:

Пожалуйста, найдите в этой строке все последовательности символов, которые:

  • Отдельно от другого текста (как слова);
  • Состоит из одной или нескольких букв английского алфавита, подчеркивание (я), дефис (ы), точка (и) или цифра (ы);
  • Конец ".htm";
  • Кроме того, часть последовательности перед ".htm" может быть чем угодно но "фу".
1 голос
/ 23 марта 2016

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

);
0 голосов
/ 28 июля 2011

Вы можете эмулировать отрицательный взгляд с помощью чего-то вроде /(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/, но программный подход был бы лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...