Как извлечь регулярные выражения с помощью 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, который заменяет и заменяет весь объект.