Como você usa o redirecionamento de saída em combinação com here-documents e cat?

44

Digamos que eu tenha um script que eu queira enviar para outro comando ou redirecionar para um arquivo (canalizando para sh para os exemplos). Suponha que estou usando bash.

Eu poderia fazer isso usando echo :

echo "touch somefile
echo foo > somefile" | sh

Eu também poderia fazer quase a mesma coisa usando cat :

cat << EOF
touch somefile
echo foo > somefile
EOF

Mas se eu substituir "EOF" por "EOF | sh", ele apenas pensa que é parte do heredoc.

Como posso fazer com que cat envie texto de stdin e depois canalize-o para um local arbitrário?

    
por strugee 28.08.2013 / 06:41

2 respostas

76

Existem várias maneiras de fazer isso. O mais simples é provavelmente isso:

cat <<EOF | sh
touch somefile
echo foo > somefile
EOF

Outra, que é uma sintaxe melhor na minha opinião:

(
cat <<EOF
touch somefile
echo foo > somefile
EOF
) | sh

Isso funciona também, mas sem o subnível:

{
cat <<EOF
touch somefile
echo foo > somefile
EOF
} | sh

Mais variações:

cat <<EOF |
touch somefile
echo foo > somefile
EOF
  sh

Ou:

{ cat | sh; } << EOF
touch somefile
echo foo > somefile
EOF

A propósito, espero que o uso de cat em sua pergunta seja um espaço reservado para outra coisa. Se não, retire assim:

sh <<EOF
touch somefile
echo foo > somefile
EOF

O que poderia ser simplificado para isso:

sh -c 'touch somefile; echo foo > somefile'

ou:

sh -c 'touch somefile
echo foo > somefile'

Redirecionando a saída em vez de canalizar

sh >out <<EOF
touch somefile
echo foo > somefile
EOF

Usando cat para obter o equivalente a echo test > out :

cat >out <<EOF
test
EOF

Vários documentos aqui

( cat; echo ---; cat <&3 ) <<EOF 3<<EOF2
hi
EOF
there
EOF2

Isso produz a saída:

hi
---
there

Veja o que está acontecendo:

  • O shell vê o ( ... ) e executa os comandos fechados em um subshell.
  • O gato e o eco são bastante simples. O cat <&3 diz para executar o cat com o descritor de arquivo (fd) 0 (stdin) redirecionado do fd 3; em outras palavras, exclua a entrada do fd 3.
  • Antes de iniciar o (...) , o shell vê os dois documentos aqui redirecionados e substitui fd 0 ( <<EOF ) e fd 3 ( 3<<EOF2 ) pelo lado de leitura dos pipes
  • Depois que o comando inicial é iniciado, o shell lê seu stdin até que o EOF seja alcançado e envia isso para o lado da escrita do primeiro canal
  • Em seguida, ele faz o mesmo com EOF2 e o lado da gravação do segundo tubo
por 28.08.2013 / 06:55
1

Eu só quero ressaltar que usar meow é tão válido quanto EOF .

Este script adicionará Meow! a um arquivo chamado cat :

#!/bin/sh
cat <<meow>> cat
Meow!
meow

Salvar como cats e torná-lo executável com chmod +x cats , depois executá-lo com ./cats :

$ ./cats
$ cat cat
Meow!
$ ./cats
$ cat cat
Meow!
Meow!

Explicação:

  • cat <<meow é a sintaxe aqui do documento . Ele instrui o script a selecionar o bloco de texto que segue essa linha até encontrar a string meow . O conteúdo será então enviado (ou canalizado).
  • >> cat pipes para o arquivo chamado cat .
  • Usar > em vez de >> sobrescreveria o arquivo em vez de anexá-lo a ele.
  • Meow! é o conteúdo do documento aqui .
  • meow é o marcador final do documento aqui . O conteúdo é, com o uso de >> , anexado a cat .

Piping tanto para stdout quanto para um arquivo:

Para fazer o encanamento que você solicita, nenhum documento aqui é necessário.

cat não pode produzir texto nem passar o texto, mas tee é uma combinação perfeita para o que você está pedindo:

echo echo | tee tee

Isso gerará a string echo e gravará echo em um arquivo chamado tee .

Você também pode passar a saída por cat , se isso fizer parte do requisito, com:

echo echo | tee tee | cat </dev/stdin

Ou apenas:

echo echo | tee tee | cat

Conteúdo do arquivo:

$ cat tee
echo
    
por 05.01.2018 / 14:23