Regex / Vim: соответствие всего, кроме шаблона, где шаблон многострочный? - PullRequest
4 голосов
/ 14 февраля 2012

Есть ли в Vim способ выполнить операцию, аналогичную

:v/PATTERN/d 

, где PATTERN - это многострочный шаблон регулярных выражений ?Я уверен, что есть способ сделать это в сценарии, но мне в основном любопытно, можно ли это сделать, используя только стандартные подстановки регулярных выражений или команды Vim, потому что на данный момент это скорее академическое, чем реальная потребность.

Мой пример следующий:

asdf

begin
   blah
end

asdf

alsdfjasf

begin
   random stuff
end
...

Я хочу получить блоки начала / конца со строками между ними, но игнорировать все, что находится за пределами блоков, в конечном итоге заканчивая

begin
   blah
end

begin
   random stuff
end
...

Мои мысли должны были сделать

:v/begin\_.\{-}end/d 

, где все не соответствовало бы тому, что было бы удалено или даже скопировано для регистрации, но очевидно: v и: g работают только в одной строке.

Затем я начал идти по пути выполнения замены и заменять все пустой строкой, которая НЕ соответствовала шаблону begin\_.\{-}end, но я не могу понять, как этого добиться, используя обходные пути или что-то еще.При регулярном поиске регулярное выражение прекрасно работает, но я не могу понять, как сказать механизму регулярных выражений найти все, НО этот шаблон.Есть идеи?

Ответы [ 3 ]

8 голосов
/ 14 февраля 2012

очистить рег a

qaq

добавить begin...end к рег a

:g/begin/,/end/y A

открыть новую вкладку

:tabnew

поставить рег a

"ap
2 голосов
/ 14 февраля 2012

Переверните его наизнанку и удалите все, разделенные шаблоном:

:%s/\%(^end\n*\|\%^\)\zs\_.\{-}\ze\%(^begin\|\%$\)//
  • \%( ... ) - группа без захвата
  • ^end\n* - конец вашего шаблона
  • \%^ - начало файла
  • \zs - не включать ничего подходящего перед этой точкой в ​​заменяемую строку
  • \_.\{-} -не жадное сопоставление чего-либо (включая символы новой строки)
  • \ze - не включайте в строку заменяемое ничего после этой точки
  • ^begin - начало вашего паттерна
  • \%$ - конец вашего паттерна
0 голосов
/ 14 февраля 2012

Команды, выполняемые g и v, могут сами принимать диапазоны, поэтому вы можете воздействовать на все, от «начала» до «конца», с помощью :g /begin/ .,/end/xxx, где xxx - команда для выполнения в этом диапазоне. Вы действительно не можете использовать это для :v, но есть несколько способов сделать это за несколько проходов, например

"mark all the lines we want to keep by putting '@' at the start of the line"
:g/^begin/ .,/^end/  s/^/@/
"delete all unmarked lines"
:v/^@/ d
"remove the markers"
:s/^@//

Конечно, предполагается, что в файле нет строк, начинающихся с @.

В качестве альтернативы вы можете удалить все между каждым «концом» и следующим «началом»

:g/^end/ +1,/^begin/-1 d

затем удалите левый край в начале и конце файла:

:1,/^begin/-1 d
:$?^end?+1,$ d

Обратите внимание на использование $?^end?+1 для поиска в обратном направлении от конца файла, чтобы найти последнюю строку, начинающуюся с «end».

N.B. последние два удалят слишком много, если файл начинается с «begin» или заканчивается «end» в этой точке, поэтому проверьте, прежде чем использовать их.

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