Vim Regex: Как искать A И B, а не C - PullRequest
       1

Vim Regex: Как искать A И B, а не C

49 голосов
/ 07 октября 2010

У меня много строк с именами президентов США: Картер, Буш, Клинтон, Обама. Некоторые содержат 1 из этих имен, некоторые 2, некоторые 3, некоторые все 4 из них (в любом порядке).

Я знаю, как искать Картера, Клинтона и Обаму ->

:g/.*Carter\&.*Clinton\&.*Obama/p

Я знаю, как искать Картер И (Клинтон ИЛИ Буш) ->

:g/.*Carter\&\(.*Clinton\|.*Bush\)/p

(наверняка есть лучшие способы сделать это)

Но я не могу понять, как искать (и я смотрел на связанные вопросы), например, для Буша и Клинтона НЕ Картера и еще меньше, как искать, например, для Буша и Клинтона НЕ (Картера ИЛИ Обамы).

Ответы [ 2 ]

51 голосов
/ 07 октября 2010

Чтобы представить НЕ, используйте отрицательное утверждение \@!.

Например, "НЕ Буш" будет:

^\(.*Bush\)\@!

или используя \v:

\v^(.*Bush)@!

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

Перевод "Буша"И КЛИНТОН И НЕ (Картер ИЛИ Обама) ":

\v^(.*Bush)&(.*Clinton)&(.*Carter|.*Obama)@!

Добавление

Чтобы объяснить связь между \& и \@=:

One&Two&Three

взаимозаменяем с:

(One)@=(Two)@=Three

Единственное отличие состоит в том, что \& непосредственно отражает \| (что должно быть более очевидным иестественно), в то время как \@= отражает Perl's (?=pattern).

14 голосов
/ 07 октября 2010

Если вы хотите использовать регулярные выражения в стиле Perl после vim, забудьте о \&: это особенность vim, которая бесполезна, так как vim также имеет подсказки, поэтому любой r1\&r2 может быть переписан как \%(r1\)\@=r2. Но взгляды лучше, поскольку есть отрицательная версия, и они также доступны в большинстве движков регулярных выражений в стиле Perl. Ваш (Bush AND Clinton AND NOT (Carter OR Obama)) может быть выражен следующим образом:

g/^\%(.*\%(Carter\|Obama\)\)\@!\%(.*Bush\)\@=.*Clinton/

Или, с очень волшебством:

g/^\v%(.*%(Carter|Obama))@!%(.*Bush)@=.*Clinton/

См. :h /\@=

О внутренней логике: упреждающий просмотр подобен ветвям: для регулярного выражения (reg1)@=reg2 при условии, что reg2 соответствует позиции N (совпадение начинается в позиции N), механизм регулярных выражений проверяет, соответствует ли reg1 также в эта позиция. Если это не так, то позиция отбрасывается, и механизм регулярных выражений пытается найти следующее возможное совпадение для reg2. То же самое для негативного прогнозирования, но с той разницей, что механизм регулярных выражений сбрасывает позицию, если reg1 соответствует .


* +1025 * Пример:

Регулярное выражение: (.b)@!a.

Строка: aba.

  1. Найдено совпадений: a совпадений в позиции 0 (<b>a</b>ba). Попытка сопоставить упреждения: . совпадения a (<b>a</b>ba) и b совпадения b (a<b>b</b>a), упреждающие совпадения, сброс позиции.
  2. Позиция 1 (a<b>b</b>a) не соответствует a.
  3. Найдено совпадений: a совпадений в позиции 2 (ab<b>a</b>). Попытка сопоставления с предварительным просмотром: . соответствует a (ab<b>a</b>), но b не совпадает: символов не осталось, предварительный просмотр завершается неудачей. Результат: регулярное выражение соответствует позиции 2.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...