Como faço para capturar stdin para uma variável sem remover nenhuma nova linha?

6

Em um script de shell ...

Como faço para capturar stdin para uma variável sem remover nenhuma nova linha?

Agora eu tentei:

var='cat'
var='tee'
var=$(tee)

Em todos os casos, $var não terá a nova linha final do fluxo de entrada. Obrigado.

ALÉM DISSO: Se houver nenhuma nova linha na entrada, a solução não deve adicionar uma .

ATUALIZAÇÃO À LUZ DA RESPOSTA ACEITA:

A solução final que usei no meu código é a seguinte:

function filter() {
    #do lots of sed operations
    #see https://github.com/gistya/expandr for full code
}

GIT_INPUT='cat; echo x'
FILTERED_OUTPUT=$(printf '%s' "$GIT_INPUT" | filter)
FILTERED_OUTPUT=${FILTERED_OUTPUT%x}
printf '%s' "$FILTERED_OUTPUT"

Se você gostaria de ver o código completo, por favor veja a página do github para expandr , um pequeno código-fonte aberto < href="http://git-scm.com/book/en/Customizing-Git-Git-Attributes"> filtro de expansão de palavra-chave git script shell que desenvolvi para fins de segurança da informação. De acordo com as regras definidas nos arquivos .gitattributes (que podem ser específicos da ramificação ) e config git , o git canaliza cada arquivo através do shell script expandr.sh sempre que verificando-o dentro ou fora do repositório. (É por isso que era fundamental preservar qualquer nova linha ou a falta dela.) Isso permite limpar informações confidenciais e trocar diferentes conjuntos de valores específicos do ambiente para teste, teste e ramos ativos.

    
por CommaToast 09.09.2014 / 02:29

3 respostas

6

As novas linhas finais são removidas antes que o valor seja armazenado na variável. Você pode querer fazer algo como:

var='cat; echo x'

e use ${var%x} em vez de $var . Por exemplo:

printf "%s" "${var%x}"

Observe que isso resolve o problema de novas linhas à direita, mas não o byte nulo um (se a entrada padrão não for texto), desde de acordo com a substituição do comando POSIX :

If the output contains any null bytes, the behavior is unspecified.

Mas as implementações do shell podem preservar os bytes nulos.

    
por 09.09.2014 / 02:37
4

Você pode usar o read integrado para realizar isso:

$ IFS='' read -d '' -r foo < <(echo bar)

$ echo "<$foo>"
<bar
>

Para um script ler STDIN, seria simplesmente:

IFS='' read -d '' -r foo

Não sei ao certo em que camadas isso funcionará. Mas funciona bem tanto no bash quanto no zsh.

    
por 09.09.2014 / 04:49
2

Você pode fazer como:

input | { var=$(sed '$s/$/./'); var=${var%.}; }

Tudo o que você fizer $var desaparecerá assim que você sair desse grupo { current shell ; } de qualquer maneira. Mas também poderia funcionar como:

var=$(input | sed '$s/$/./'); var=${var%.}
    
por 09.09.2014 / 03:07