Фильтром называется утилита, которая принимает текст из STDIN и выдает текст в STDOUT. Может отфильтровывать, например, строки, как grep. Может что-то делать с ними, как fmt или однострочники на Perl. Может делать вообще что угодно, скажем, переводить или редактировать грамматику или, скажем, заменять недопустмые слова на эвфемизмы. В этой заметке обсудим средства Вим для пропускания текста через внешние фильтры.
Прежде всего, вспомним, как вызывать команды bash (или какая у вас оболочка) из Вим: посредством команды "восклицательный знак". Например, так:
:!ls -lstr *.txt
Восклицательный знак используется и в других случаях общения с системой.
Так,
:r! команда_bash
позволяет не просто выполнить команду, но вставить ее выдачу в текст. Команда :r (:read) вообще позволяет вставить файл, но в частности и выдачу команды bash.
Это удобно, например, для вставки списка файлов, или для искомого системным grep-ом, хотя в Вим есть для поиска по файлам удобные средства. Можно запустить что угодно, от однострочника на Перле до каких угодно программ, и вставить в текст то, что они выдадут на STDOUT.
Но это пока выполнение внешней команды без передачи ей текста. Но вот команда
:диапазон! фильтр
передает указанный диапазон строк внешнему фильтру и вставляет его выдачу в файл. Примеры:
.,+3!fmt
.,$!perl -E 's/42/666/g'
Можно немного упростить себе жизнь. Например, выделить текст и далее
!фильтр.
А ! с движением выпишет диапазон за вас. Скажем,
!3jfmt
Наконец, !!фильтр пропустит через фильтр указанное число строк:
12!!fmt
Указанная утилита fmt форматирует текст, вставляя символы конца строки, но с умом. При этом длинные строки укорачиваются, удобно бывает, см. man. Впрочем, для форматирования строк есть команда Вим gq. О ней в другой раз.
Я наиболее часто пользуюсь однострочниками. Например, удобно перевести столбец таблицы данных в другие единицы:
.,$! perl -pa -E '$F[1]*=3600; say"@F"'
пропускает строки с текущей (.) до конца ($) через скрипт, который обрабатывает входной поток STDIN построчно (-n), разделяет строку на слова (-a) и кладет их в массив @F. Берем второй элемент (второй столбец) $F[1] и делаем с ним что хотим. Потом выводим на STDOUT.
Удачи, коллеги!