Como ler a entrada de várias linhas de stdin em variável e como imprimir um fora em shell (sh, bash)?
Pergunta
O que eu quero fazer é o seguinte:
- lido em linha de entrada múltipla de
stdin
emA
variável - fazer várias operações em
A
-
A
tubulação sem perder símbolos delimitadores (\n
,\r
,\t
, etc) para outro comando
O problema atual é que, eu não posso lê-lo com comando read
, porque ele pára de ler a nova linha.
Eu posso ler stdin com cat
, como este:
my_var=`cat /dev/stdin`
, mas então eu não sei como imprimi-lo. Assim que os nova linha, tabulação e outros delimitadores ainda estão lá.
Meu script olhares amostra como este:
#!/usr/local/bin/bash
A=`cat /dev/stdin`
if [ ${#A} -eq 0 ]; then
exit 0
else
cat ${A} | /usr/local/sbin/nextcommand
fi
Solução
Esse é um trabalho para mim:
myvar=`cat`
echo "$myvar"
As aspas em torno $myvar
são importantes.
Outras dicas
Em Bash, há uma forma alternativa; man bash
menciona:
O
$(cat file)
substituição de comando pode ser substituído pelo$(< file)
equivalente, mas mais rápido.
$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
T faz o trabalho
#!/bin/bash
myVar=$(tee)
Sim ele funciona para mim também. Obrigado.
myvar=`cat`
é o mesmo que
myvar=`cat /dev/stdin`
Bem, sim. A partir da página homem bash
:
encerrando caracteres entre aspas duplas preserva o valor literal de tudo caracteres dentro das citações, com exceção de $, `, \, e, quando a expansão história é ativado, !. Os caracteres $ e ` mantêm o seu significado especial dentro de aspas duplas.
Se você se preocupam com a preservação novas linhas à direita no final da saída, use o seguinte:
myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"
Isto usa o truque de aqui .
[atualizado]
Esta atribuição irá travar indefinidamente se não há nada no tubo ...
var="$(< /dev/stdin)"
Podemos evitar isso, porém, fazendo um read
tempo limite para o primeiro caractere. Se ele expirar, o código de retorno será maior do que 128 e nós vamos saber o tubo de STDIN (a.k.a /dev/stdin
) está vazio.
Caso contrário, ficamos com o resto do STDIN por ...
- configuração
IFS
para NULL para apenas o comandoread
- desligar escapes com
-r
- eliminando delimitador de leitura com
-d ''
. - e, finalmente, acrescentando que ao caráter chegamos inicialmente
Assim ...
__=""
_stdin=""
read -N1 -t1 __ && {
(( $? <= 128 )) && {
IFS= read -rd '' _stdin
_stdin="$__$_stdin"
}
}
Esta técnica evita usar var="$(command ...)"
comando de substituição que, pelo projeto, sempre retirar quaisquer novas linhas de fuga.
Se é preferido comando de substituição, para preservar a fuga novas linhas que pode incluir uma ou mais caracteres de delimitação para a saída dentro do $()
e, em seguida, tira-los fora.
Por exemplo ($(parens)
nota no primeiro comando e ${braces}
no segundo) ...
_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"