Есть ли способ сделать негативный просмотр в regex vim?

В Vim существует ли способ поиска строк, которые соответствуют say abc, но также не содержат xyz позже в строке? Таким образом, следующие строки будут соответствовать:

The abc is the best
The first three letters are abc

и следующее не будет соответствовать:

The abc is the best but xyz is cheaper
The first three letters are abc and the last are xyz

Я знаю о синтаксисе, как показано ниже:

/abc\(xyz\)\@!

но это позволяет избежать соответствия abcxyz, а не если между ними есть что-то среднее, например abc-xyz. Использование

/abc.*\(xyz\)\@!

также не работает, поскольку в строке, где xyz не соответствует.

(Я должен отметить, что в командной строке я сделал бы что-то вроде grep abc <infile | grep -v xyz, но я хотел бы сделать это интерактивно в Vim.)

Ответы

Ответ 1

Ваша попытка была довольно близка; вам нужно вытащить .*, что позволяет произвольное расстояние между совпадением и подтвержденным более поздним несоответствием на негативный прогноз вперед:

/abc\(.*xyz\)\@!

Я думаю, это работает, потому что не-совпадение выполняется для всех возможных совпадений .*, и только когда все ветки были исчерпаны, объявлен как \@!.

Ответ 2

Это работает для меня /abc\(.*xyz\)\@!

Ответ 3

Хотя ваш вопрос касается взгляда, я нашел его при поиске lookbehind. Таким образом, я отправляю решение для поиска, чтобы другие могли его найти.

Если вы ищете pattern2, которому не предшествует pattern1, это отрицательный lookbehind, выполните поиск:

\(pattern1\)\@<!pattern2

Ответ 4

Думаю, я напишу это как /abc\(\(xyz\)\@!.\)*$

Я не уверен, что это быстрее, чем другие предложения (я думаю, это может быть, так как он проверяет каждую позицию только один раз), но это делает концептуальный смысл следующим:

"abc, за которым следует любое, что не является xyz, любое количество раз до конца строки

Мне нравится это лучше, чем "abc, за которым следует все, за чем не следует xyz", как в других упомянутых шаблонах.