Ответ 1
Я думаю, что :w !tee
будет работать отлично,
Есть ли возможность записать содержимое текущего vim-буфера в stdout?
Я хотел бы использовать vim для редактирования контента, который был передан через stdin - без необходимости временного файла для извлечения измененного содержимого (в Linux/Unix).
Возможно ли, что плагин / script, который действует при выходе или сохранении, помещает содержимое буфера в стандартный вывод?
Я думаю, что :w !tee
будет работать отлично,
Поскольку вы используете Linux/Unix, вам также может быть интересно попробовать moreutils. Он предоставляет команду под названием vipe
, которая читает с stdin
, позволяет редактировать текст в $EDITOR
, а затем печатать измененный текст на stdout
.
Поэтому убедитесь, что вы установили свой редактор в Vim:
export EDITOR = vim
И затем вы можете попробовать следующие примеры:
cat/etc/fstab | Vipe
cut -d '' -f2/etc/mtab | vipe | меньше
Чтение из stdin:
echo "hey" | vim -
Когда вы :w
, вам все равно придется указывать имя файла.
Программы, которые используют vim
как их EDITOR
, например crontab -e
, передают ему имя файла, чтобы пользователь мог просто :x
и не беспокоиться о именах файлов.
ИЗМЕНИТЬ
Вы также можете сделать что-то вроде этого:
mkfifo /tmp/some_pipe
echo "hey" > /tmp/some_pipe ; cat /tmp/some_pipe
И из другого процесса (или терминала)
vim /tmp/some_pipe
Остерегайтесь того, что запись в канал будет блокироваться до тех пор, пока что-то не прочитает его, и чтение будет блокироваться до тех пор, пока что-то не запишет на него, поэтому было бы безопаснее использовать обычные файлы.
Чтобы напечатать буфер для стандартного вывода оболочки, vim
нужно запустить в режиме Ex, иначе он откроет "обычный" способ со своим окном и очистит любые выходные буферы при выходе.
Вот простейший рабочий пример:
$ echo foo | vim -es '+%print' '+:q!' /dev/stdin
foo
Для предотвращения дополнительных раздражающих сообщений необходимо указать специальный дескриптор файла для стандартного ввода (/dev/stdin
).
И вот несколько примеров синтаксического анализа строк:
$ echo This is example. | vim -es '+s/example/test/g' '+%print' '+:q!' /dev/stdin
This is test.
$ echo This is example. | vim - -es '+s/example/test/g' '+%print' '+:q!'
Vim: Reading from stdin...
This is test.
Вот простой пример с использованием ex
, который эквивалентен vi -e
:
ex -s +%p -cq /etc/hosts
по теме:
Использование :print
будет записывать в stdout, особенно если vim запускается с параметрами -E
и -s
, которые заставляют его работать невзаимодействующим и бесшумным. См. :h -E
и :h -s-ex
:
The output of these commands is displayed (to stdout):
:print
:list
:number
:set to display option values."
Используйте :%print
для печати всего текущего буфера.
Попробуйте что-то вроде:
{ FROMCMD | vim - 8>&1 >&9 | tac | tac | TOCMD; } 9>&1
и используйте ': w! cat > & 8', когда вы закончите редактирование
'tac | tac 'гарантирует, что TOCMD не получит никаких данных до тех пор, пока вы не получите vim, это полезно, только если TOCMD пишет на терминал, чтобы он не делал беспорядок, пока vim все еще работает.
Обратите внимание, что запуск "меньше" в качестве вашего TOCMD (или любой другой программы, выполняющей некоторые манипуляции с терминалами) не будет работать так, как ожидалось, потому что, даже если вы задерживаете данные, процессы все равно запускаются "в одно и то же время" и могут доступ к терминалу в одно и то же время.
Вы также можете использовать pipe.vim. Он использует временный файл, но по крайней мере вам не нужно беспокоиться об этом в своем собственном script.
Во вторую часть вашего вопроса вы используете опцию командной строки -s
с vim для переназначения :w
на что-то другое (например, :w !tee
).
vim может использоваться в трубах как полнофункциональный фильтр с явными именами для stdin и stdout, как в следующем примере:
echo xxx |
vim \
-esnN -i NONE \
+'1 s /x/y/g | 1 s /^/Hallo / | x! /dev/stdout' \
/dev/stdin |
cat -n
Сокращение /dev/stdin
с помощью -
не будет работать даже с флагом -v
.