Удалить все, кроме шаблона

Скажем, это мой текст:

это мой текст this
мой текст - это мой текст
мой текст - это

Я хотел бы выделить весь текст, кроме шаблона, и удалить выделенный текст.
возможная ошибка text: это должен быть результат.

текст
texttext
текст

Я нашел код, как выбрать весь текст, кроме шаблона:
\%(\%(.{-}\)\@!text\zs\)*

однако я не знаю, как удалить весь выделенный текст.
Это не работает:
:%s/\%(\%(.{-}\)\@!bell\zs\)*//

Кто-нибудь может мне помочь?

Ответ 1

Попробуйте следующее:

:%s/\(^\|\(text\)\@<=\).\{-}\($\|text\)\@=//g

Пояснение:

\(^\|\(text\)\@<=\)     # means start of line, or some point preceded by "text"
.\{-}                   # as few characters as possible
\($\|text\)\@=          # without globbing characters, checking that we reached either end of line or occurrence of "text".

Другой способ сделать это:

  • Создайте функцию, которая подсчитывает совпадения шаблона в строке (см. :help match(), чтобы помочь вам в разработке)
  • Использование: :%s/.*/\=repeat('text', matchcount('text', submatch(0)))

Ответ 2

Простите меня, потому что я не эксперт по vim, но не ожидал бы поиска с v найти обратное, чтобы вы могли сделать что-то вроде этого?

:v/pattern/d

Ответ 3

Я реализовал умное регулярное выражение Benoit как пользовательское :DeleteExcept команду :DeleteExcept в моем плагине PatternsOnText. Он также предлагает другие связанные команды, такие как :SubstituteExcept или :SubstituteInSearch.

OP пример будет

:%DeleteExcept /text/

Сравнивая это с явной командой @Benoit (:%s/\(^\|\(text\)\@<=\).\{-}\($\|text\)\@=//g), намного проще