Como ler a entrada de várias linhas de stdin em variável e como imprimir um fora em shell (sh, bash)?

StackOverflow https://stackoverflow.com/questions/212965

  •  03-07-2019
  •  | 
  •  

Pergunta

O que eu quero fazer é o seguinte:

  1. lido em linha de entrada múltipla de stdin em A variável
  2. fazer várias operações em A
  3. 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
Foi útil?

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 comando read
  • 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%|||}"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top