Como editar o conteúdo da entrada padrão?

15

Gostaria de editar o conteúdo no vim, que foi gerado dinamicamente a partir da linha de comando, sem o arquivo ainda.

No exemplo:

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

mas está falhando com os erros:

Vim: Aviso: A entrada não é de um terminal

Vim: Erro ao ler a entrada, saindo ...

É possível conseguir isso?

kenorb
fonte
:help stdin... É incrível a rapidez com que as respostas são encontradas, fazendo a pergunta da documentação incorporada.
traço-tom-bang

Respostas:

23

Você deve usar -no lugar do nome do arquivo na linha de comando:

echo This is example. | vim -

O comando acima abrirá um buffer sem nome preenchido com o texto lido da entrada padrão.

toro2k
fonte
7
Usar um -para stdin é praticamente o padrão para ferramentas de linha de comando;
Martin Tournoij 12/02/2015
6

Esta é apenas uma observação divertida sobre bashe readline, mas se você definir sua EDITORvariável de ambiente como vim, pressionar Ctrl+ x+ eabrirá a linha atual vim. Além disso, se você digitar Meta(Alt/Opt/Esc)+ Ctrl+ e, o bash executará uma expansão no local na linha de comando atual, ou seja:

$ echo $EDITOR # Assuming EDITOR was set

com Meta(Alt/Opt/Esc)+ Ctrl+ ese tornaria

$ echo vim # Assuming EDITOR was set

com Ctrl+ x+ ese tornaria

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

Observe que, ao sair do vim, o conteúdo do buffer do vim é executado na linha de comando.

Esses recursos se tornam muito úteis para mim quando eu quero executar comandos de várias linhas no bash, como loops ou programas que exigem instruções aqui, e fornece uma maneira interessante de salvar um pouco do histórico da linha de comando em arquivo para uso posterior.

Então, para responder à pergunta original, você também pode escrever,

$ This is an example

e pressione Ctrl+ x+ epara carregá-lo vim. Além disso, você poderia ter,

 $ $(cat /etc/hosts)

e faça Meta(Alt/Opt/Esc)+ Ctrl+ eentão Ctrl+ x+ e, que colocaria todo o arquivo hosts em uma linha e o carregaria vim(provavelmente não é o melhor uso desses recursos - no entanto, a utilidade desses métodos pode ser extrapolada a partir dos poucos exemplos discutidos aqui).

Observe que eu assumo que você readlineestá definido para o emacsmodo. Se você readlineestiver definido como vimmodo, poderá descobrir facilmente as ligações relevantes usando o comando:

bind -p

e procurando por edit-and-execute-commandou shell-expand-line, que foram respectivamente associados às ligações Ctrl+ x+ ee Meta(Alt/Opt/Esc)+ Ctrl+ e.

HAL 9001
fonte
Você pode dizer ao bash para usar as ligações de teclas vi em vez do emacs. Use set -o vipara ligá-lo. Em seguida, você pode apenas usar o vmapeamento no modo normal para editar o comando atual no seu editor.
Quincy Bowers
11
Certamente, este é um ótimo truque para editar a linha de comando usando o vi, mas há pelo menos dois problemas ao usar este método para ler o texto do stdin: 1. shell-expand-lineremova novas linhas do texto expandido e 2. edit-and-execute-commandtente executar o comando escrito no buffer , seja o que for salvo ou não, quando você sair do vi.
toro2k 12/02
Uau, isso é incrível. Eu aprendo uma coisa nova sobre readline todos os dias, parece ...
Doorknob
2

No bash, achei útil usar a substituição de processo usando a <(command)sintaxe, no exemplo:

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

Veja também:

kenorb
fonte
4
Observe que isso não funcionará em todas as conchas. Eu acho que ele só vai funcionar em bashe zsh(e não sh, ksh, dash, fish, csh, tcsh, etc.)
Martin Tournoij
@Carpetsmoker Deve funcionar no ksh88 e acima, acho, mas sim, a substituição do processo não é POSIX.
muru
4
E preste atenção para não se enganar! Quando você inicia o Vim dessa maneira, ele abre um buffer para um arquivo como /proc/PID/fd/FD. Se você gravar o buffer e sair, o Vim não se queixa, mas o arquivo para o qual você escreveu será removido pelo sistema operacional. Usando -como o nome do arquivo, o buffer aberto não possui nenhum arquivo associado; portanto, se você tentar sair sem (desde que você não use um comando bang ou similar), o Vim o avisará.
toro2k 12/02
11
Isso é bom porque generaliza bem para vimdiff <(echo foo) <(echo bar).
wchargin
@ toro2k Para acompanhar, parece que você usa :nexte :prevrelê o fluxo e não recebe nada. Também vale a pena mencionar que os processos não são paralelos entre si - por exemplo, cat <(sleep 3; echo a) <(echo b)impressões em ordem - e enquanto catintercala gravações e leituras, vimaguarda o arquivo para "concluir a leitura" antes de exibir tudo, exceto o quadro externo.
John P
-1

Se não for necessário usar um pipeline para um novo Vim, você poderá usar a capacidade do Vim para extrair a saída de comandos para o buffer atual, juntamente com um buffer sem backup de arquivo (como com :newou editar um arquivo inexistente)

:read!cat /etc/hosts no modo de comando, a saída será colocada no buffer atual abaixo da posição atual do cursor.

Além de ter que excluir a primeira linha vazia que permanece quando isso é feito em um buffer vazio, isso funciona bem e é especialmente conveniente se o Vim já estiver em execução.

ewatt
fonte
11
Como isso responde à pergunta?
19715 muru
Ele pega a saída do comando e o coloca no vim.
ewatt