Como cat dois heredocs? [duplicado]

5

Quando o gato recebe dois heredocs, ele gera apenas o segundo.

$ cat <<HERE
> adsf
> qwer
> HERE
adsf
qwer
$ cat <<HERE <<ALT
> qwer
> asdf
> HERE
> zxcv
> yuop
> ALT
zxcv
yuop

Isto também se aplica se for dado um heredoc e um arquivo, embora eu note que, se eu der um arquivo e um heredoc (ordem invertida), ele ainda só gera o arquivo. No entanto, se eu der ao gato dois arquivos, ele produzirá os dois corretamente.

Por que o gato se comporta assim?

    
por Benubird 02.04.2015 / 13:59

4 respostas

2

Existem várias maneiras de redirecionar a entrada padrão de um comando ( stdin ):

  • command <file Redirecionamento simples: stdin será o arquivo
  • command <&n Duplicar outro fd: stdin será uma duplicação de fd n
  • command <<word Aqui doc: stdin será o script até word
  • other | command Pipe: stdin vem da saída de other

Como existe apenas um stdin, somente um redirecionamento para stdin pode ser efetivo. A regra simples é que o último ganha (apesar de todos eles serem aplicados por sua vez, o que é importante se os redirecionamentos incluírem duplicação fd).

O último formulário acima fornece uma maneira simples de concatenar várias entradas:

{ cat <<END; cat <<END; } | command
The first here-doc
END
The second here-doc
END

Alguns shells fornecem formulários de redirecionamento adicionais. Por exemplo, bash , ksh e zsh permitem fornecer "here-strings": command <<<word .

    
por 02.04.2015 / 17:52
7

Em sistemas com /dev/fd/x :

cat - << E0 /dev/fd/3 3<< E3
foo bar
E0
bar baz
E3

Isto é, abra os dois documentos aqui em diferentes descritores de arquivos. Se você abrir ambos no fd 0, é claro que a última abertura substitui as anteriores.

O acima seria mais útil com comandos como paste .

Observe que zsh tem o recurso MULT_IOS (ativado por padrão e desabilitado com unsetopt MULT_IOS ou ao emular outros shells) pelo qual se você redirecionar um descritor de arquivo para entrada mais de uma vez, zsh alimenta a concatenação do entradas correspondentes (através de um tubo em um processo separado). Então, em zsh:

$ cat << E1 << E2
heredoc> foo
heredoc> E1
heredoc> bar
heredoc> E2
foo
bar
O stdin de

cat é um pipe e o zsh alimenta o conteúdo dos dois documentos aqui em sequência na outra extremidade do pipe.

Existe um recurso semelhante para o redirecionamento de saída.

ls > a > b

torna ls gravar em um canal e o zsh grava em a e b ao mesmo tempo (como uma forma de tee ), enquanto no outro stdout de ls do shell seria apenas b (e a teria sido truncado, mas nunca gravado em).

    
por 02.04.2015 / 15:17
5

cat sem args lerá sua entrada padrão (isto é, descritor de arquivo 0) até o final do arquivo, e copiará isso para sua saída padrão (ou seja, descritor de arquivo 1).

cat com um ou mais argumentos tentará abrir esses argumentos como sua entrada e copiará os dados para sua saída padrão. Ele ignora a entrada padrão nesse caso, o que é uma coisa boa, pois seria bastante irritante ter que digitar ctrl + D depois de fazer, e. %código%. Isso explica por que cat /etc/motd está ignorando o documento "aqui" quando também recebe um nome de arquivo. Como um caso especial, você pode fornecer cat como um nome de arquivo que é interpretado como significando "entrada padrão" - que você pode combinar um arquivo com um documento "aqui".

O shell só pode passar um arquivo como entrada padrão para um comando, então não faz muito sentido passar dois documentos "aqui" para um comando; somente o último irá torná-lo como entrada padrão para o comando.

    
por 02.04.2015 / 14:13
1

Eu não tenho ideia de onde isso pode ser útil, mas:

cat <<HERE
qwer
asdf
$(cat <<ALT
zxcv
yuop
ALT
)
HERE
    
por 02.04.2015 / 15:03