Заменить регулярное выражение в vim выводом, созданным консольной командой, в которой это выражение является аргументом?

Заменить регулярное выражение в vim выводом, созданным консольной командой, в которой это выражение является аргументом?

Допустим, у меня есть файл со следующим содержимым:

Это _файл_, содержащий некоторые _специальные_ ключевые слова, которые я _хотел бы_ заменить.

Я могу выполнить поиск и замену специальных ключевых слов с помощью "%s/_*_/something", но я хотел бы, чтобы "something" было выводом внешней команды. Возможно ли это в vim, или мне нужно использовать awk?

решение1

Да, можно. Смотрите :help sub-replace-special; \=позволяет вам заменить выражением Vim. И system()может выполнить внешнюю команду и вернуть ее вывод. Смотрите мой тривиальный пример с hostname. Обратите внимание, что мне пришлось использовать substitute(), чтобы избавиться от завершающего символа(ов) новой строки в выводе.

:%s/_[^_]*_/\=substitute(system('hostname'),'\n','','g')/g

PS: Я также исправил ваш шаблон регулярного выражения, чтобы он соответствовал вашему примеру.

решение2

В ответе Инго, который мне очень помог, я не вижу, как сослаться на подшаблон соответствия и использовать его в качестве аргумента команды оболочки («создается консольной командой с выражением в качестве аргумента»).

В моем случае у меня были строки журнала следующего вида: [<unix timestamp>] <message>, т. е [1406844000] foobar. Я хотел предварить их временем в удобной для чтения форме.

Следующая команда vim сопоставляет временную метку (submatch 1) и сообщение (остальное, submatch 2) и добавляет строку времени из команды date:

:% s/^\[\(\d\+\)\] \(.*\)$/\=substitute(system('date -d @'.submatch(1)),'\n', '', 'g').': ['.submatch(1).'] '.submatch(2)/

[1406844000] foobarполучает Fr 1. Aug 00:00:00 CEST 2014: [1406844000] foobar.

НТН

решение3

Для подстановки base64 в файле ldiff:

:%s/:: \(.*\)$/\=substitute(': ' . system('echo '.submatch(1).'|base64 -d'),'\n','','g')/

Связанный контент