Как редактировать контент со стандартного ввода?


15

Я хотел бы редактировать содержимое в vim, которое было динамически сгенерировано из командной строки, но при этом еще не было файла.

В примере:

$ echo This is example. | vim /dev/stdin
$ cat /etc/hosts | vim /dev/stdin

но это с ошибками:

Vim: Предупреждение: вход не от терминала

Vim: Ошибка чтения ввода, выход ...

Можно ли этого добиться?


:help stdin... Удивительно, как быстро можно найти ответы, задавая вопрос о встроенной документации.
dash-tom-bang

Ответы:


24

Вы должны использовать -вместо имени файла в командной строке:

echo This is example. | vim -

Приведенная выше команда откроет безымянный буфер, заполненный текстом, считанным из стандартного ввода.


7
Использование -for stdin довольно стандартно для инструментов командной строки;
Мартин Турной

6

Это всего лишь забавная заметка о bashи readline, но если вы установите EDITORпеременную окружения на vim, нажатие Ctrl+ x+ eоткроет текущую строку в vim. Кроме того, если вы введете Meta(Alt/Opt/Esc)+ Ctrl+ e, bash выполнит расширение на месте в текущей командной строке, то есть:

$ echo $EDITOR # Assuming EDITOR was set

с Meta(Alt/Opt/Esc)+ Ctrl+ eстанет

$ echo vim # Assuming EDITOR was set

с Ctrl+ x+ eстанет

1 echo vim # Assuming EDITOR was set
~
~
/tmp/sometmpbufferfile

Обратите внимание, что после выхода из vim содержимое буфера vim выполняется в командной строке.

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

Чтобы ответить на исходный вопрос, вы также можете написать:

$ This is an example

а затем нажмите Ctrl+ x+ , eчтобы загрузить его в vim. Также вы могли бы иметь,

 $ $(cat /etc/hosts)

и выполните Meta(Alt/Opt/Esc)+ Ctrl+, eзатем Ctrl+ x+ e, что поместит все файлы хостов в одну строку и загрузит их vim(вероятно, это не лучшее использование этих функций - однако полезность этих методов может быть экстраполирована из нескольких рассмотренных примеров). Вот).

Обратите внимание, что я предполагаю, что у вас readlineустановлен emacsрежим. Если у вас readlineустановлен vimрежим, вы можете легко обнаружить соответствующие привязки с помощью команды:

bind -p

и поиск edit-and-execute-commandили shell-expand-line, которые были соответственно связаны с привязками Ctrl+ x+ eи Meta(Alt/Opt/Esc)+ Ctrl+ e.


Вы можете указать bash использовать привязки клавиш vi вместо emacs. Используйте, set -o viчтобы включить его. Затем вы можете просто использовать vотображение в обычном режиме для редактирования текущей команды в вашем редакторе.
Куинси Боуэрс

1
Конечно, это отличный трюк для редактирования командной строки с использованием vi, но при использовании этого метода для чтения текста из stdin есть по крайней мере две проблемы: 1. shell-expand-lineудалить символы новой строки из расширенного текста и 2. edit-and-execute-commandпопытаться выполнить команду, записанную в буфере независимо от того, сохранен он или нет, когда вы выйдете из vi.
toro2k

Вау, это круто. Кажется, я каждый день узнаю что-то новое о readline ...
Дверная ручка

2

В bash я нашел полезным использовать подстановку процессов с использованием <(command)синтаксиса, например:

vim <(echo This is example.)
vim <(cat /etc/hosts)

Смотрите также:


4
Обратите внимание, что это не будет работать во всех оболочках. Я думаю , что это будет работать только в bashи zsh(и не sh, ksh, dash, fish, csh, tcshи т.д.)
Мартин Tournoij

@Carpetsmoker Должен работать в ksh88 и выше, я думаю, но да, подстановка процессов - это не POSIX.
Муру

4
И обратите внимание, чтобы не обманывать себя! Когда вы запускаете Vim таким образом, он открывает буфер для файла вроде /proc/PID/fd/FD. Если вы напишите буфер и выйдете, Vim не будет жаловаться, но файл, в который вы записали, будет удален ОС. Использование в -качестве имени файла открытого буфера не имеет связанного с ним файла, поэтому, если вы попытаетесь выйти без (если вы не используете команду bang или что-то подобное) сохранения Vim предупредит вас.
toro2k

1
Это хорошо, потому что хорошо обобщает vimdiff <(echo foo) <(echo bar).
wchargin

@ toro2k Чтобы продолжить, это похоже на использование :nextи :prevперечитывание потока и ничего не получает. Стоит также упомянуть, что процессы не параллельны друг другу - например, cat <(sleep 3; echo a) <(echo b)печатаются по порядку - и пока catчередует записи и чтения, vimждет, пока файл «закончит чтение», прежде чем отобразить все, кроме внешнего кадра.
Джон П,

-1

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

:read!cat /etc/hosts в командном режиме поместит вывод в ваш текущий буфер ниже текущей позиции курсора.

Помимо необходимости удалять пустую первую строку, которая остается, когда это делается в пустом буфере, это работает хорошо и особенно удобно, если Vim уже запущен.


1
Как это отвечает на вопрос?
Муру

Он принимает выходные данные команды и помещает их в vim.
Ewatt
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.