Есть ли способ сделать отрицательный lookahead в Vim regex?
в 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.)
4 ответов
ваша попытка была довольно близка; вам нужно тянуть .*
это позволяет произвольное расстояние между совпадением и утвержденным позже несоответствием в негативный взгляд вперед:
/abc\(.*xyz\)\@!
Я думаю, это работает, потому что не-матч предпринимается для всех возможных матчей .*
, и только когда все ветви исчерпаны, это \@!
объявлен выполнены.
хотя ваш вопрос о lookahead, я нашел его во время поиска lookbehind. Таким образом, я публикую решение lookbehind, чтобы другие могли его найти.
Если вы ищите pattern2
не предшествует pattern1
, то есть отрицательный lookbehind, искать:
\(pattern1\)\@<!pattern2
думаю, я бы написал это как /abc\(\(xyz\)\@!.\)*$
Я не уверен, что это быстрее, чем другие предложения (я думаю, что это может быть, так как он проверяет каждую позицию только один раз), но это имеет концептуальный смысл как:
"abc, за которым следует все, что не является xyz, любое количество раз до конца строки"
мне это нравится больше, чем" abc, за которым следует что-либо, за чем не следует xyz", как в других упомянутых шаблонах.