Как извлечь регулярные выражения с помощью Vim

Пример:

case Foo:
    ...
    break;
case Bar:
    ...
    break;
case More: case Complex:
    ...
    break:
...

Я хотел бы получить все соответствия регулярных выражений (весь соответствующий текст или даже лучше, часть между \( и \)) RegEx case \([^:]*\):, которая должна дать что-то вроде (в новом новом файл):

Foo
Bar
More
Complex
...

Другим примером использования является извлечение некоторых частей, использование URL-адресов изображений из HTML файла.

Есть ли простой способ скопировать все соответствия RegEx и поместить их в буфер в Vim?

Примечание: он похож на извлекать текст с помощью vim, однако мне также интересно удалить строки, которые не соответствуют предпочтительно без огромного или сложного RegEx.

Ответы

Ответ 1

Существует общий способ сбора совпадений паттернов по всему фрагменту текста. Эта техника использует замену с помощью функция выражения команды :substitute (см. :help sub-replace-\=). Основная идея заключается в использовании замены перечисление всех совпадений шаблонов для оценки хранения выражения их без замены.

Сначала рассмотрим сохранение совпадений. Чтобы сохранить последовательность совпадающих текстовых фрагментов, удобно использовать список (см. :help List). Однако изменить список невозможно прямо, используя команду :let, так как нет способа выполните команды Ex в выражениях (включая выражения \= substitute). Тем не менее, мы можем назвать одну из функций, которые изменяют список на месте. Для Например, функция add() предназначена для добавления заданного элемента в (см. :help add()).

Другая проблема заключается в том, как избежать изменения текста во время работы замена. Один из подходов состоит в том, чтобы сделать шаблон всегда совпадение нулевой ширины, добавляя \ze или добавляя к нему атомы \zs (см. :help /\zs, :help /\ze). Шаблон, измененный таким образом захватывает пустую строку, предшествующую или предшествующую появлению исходный шаблон в тексте (такие совпадения называются совпадениями с нулевой шириной в Вим; см. :help /zero-width). Затем, если текст замены также пустая, замена ничего не меняет: она просто заменяет совпадение нулевой ширины с пустой строкой.

Так как функция add(), а также большая часть списка, изменяющего функции, возвращает ссылку на измененный список, для нашей техники чтобы работать, нам нужно как-то получить от него пустую строку. Простейший путь - извлечь из него подсписку нулевой длины, указав диапазон индексов таких, что начальный индекс больше конечного.

Объединяя вышеупомянутые идеи, мы получаем следующую команду Ex.

:let t=[] | %s/\<case\s\+\(\w\+\):\zs/\=add(t,submatch(1))[1:0]/g

После его выполнения все совпадения первой подгруппы накапливаются в списке, на который ссылается переменная t, и может использоваться как is или обрабатывается каким-то образом. Например, чтобы вставить содержимое списка один по одному в отдельных строках в режиме Вставки, введите

Ctrl + R =t Enter

Чтобы сделать то же самое в обычном режиме, просто используйте команду :put:

:pu=t

Ответ 2

Хотя для выполнения вашего примера невозможно написать однострочный вкладыш, трудно ввести команды, такие как :%s/case \([^:]*\):/\=.../ в интерактивном режиме.

Я предпочитаю использовать vim-grex со следующими шагами:

  • Используйте / для проверки соответствия регулярного выражения ожидаемым строкам. Например: /^\s*\<case\s\+\([^:]*\):.*$<Enter>
  • Выполнить :Grey. Он выравнивает строки, соответствующие текущему шаблону поиска.
  • Откройте новый буфер :new и т.д.
  • Поместите протянутые строки на p и т.д.
  • Обрезать неинтересные части на :%s//\1/.

Ответ 3

:g/^case\s\L\l\+\scase.*/s/case/\r&/g
:let @a=''|g/^case\s\L\l\+:/y A

Теперь откройте новый буфер или файл tmp и aply:

"ap
:%s_^\vcase ([^:]+):_\1_

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

:g/^case\s\L\l\+\scase.*/s/case/\r&/g
:v/^case\s\L\l\+:/d
:%s_^\vcase ([^:]+):_\1_

Ответ 4

Как использовать vim regex для извлечения слова из следующей строки, учитывая, что "help" может быть любым словом, например "rust" или "perlang".

vim:tw=78:ts=8:ft=help:norl:

Решение:

let foo = substitute(foo, '^\s*vim:.*:ft=\([a-z]\+\).*:\s*$', '\1', '')
echo "foo: '" . foo . "'"

Печать:

foo: 'help'

Гуру медитации: что здесь происходит?

Возьмите строку в переменной foo и сопоставьте ее, чтобы указать начало строки, любое количество пробелов, слово vim и буквенное двоеточие, затем любое количество любых символов, за которыми следует двоеточие ft = с любым словом с буквами, затем что угодно и утверждать, что строка заканчивается двоеточием. Бросьте содержимое переменной в регистр с именем 1, затем верните его обратно в параметр 2, который заменяет и заменяет весь объект.