web-dev-qa-db-fra.com

Comment utilisez-vous la redirection de sortie en combinaison avec here-documents et cat?

Disons que j'ai un script que je veux diriger vers une autre commande ou rediriger vers un fichier (canalisation vers sh pour les exemples). Supposons que j'utilise bash.

Je pourrais le faire en utilisant echo:

echo "touch somefile
echo foo > somefile" | sh

Je pourrais aussi faire presque la même chose en utilisant cat:

cat << EOF
touch somefile
echo foo > somefile
EOF

Mais si je remplace "EOF" par "EOF | sh", il pense simplement que cela fait partie de l'hérédoc.

Comment puis-je faire en sorte que cat génère du texte à partir de stdin, puis le redirige vers un emplacement arbitraire?

64
strugee

Il existe plusieurs façons de procéder. Le plus simple est probablement celui-ci:

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

Un autre, qui est une syntaxe plus agréable à mon avis:

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

Cela fonctionne également, mais sans le sous-shell:

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

Plus de variations:

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

Ou:

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

Soit dit en passant, je m'attends à ce que l'utilisation de cat dans votre question soit un espace réservé pour autre chose. Sinon, retirez-le, comme ceci:

sh <<EOF
touch somefile
echo foo > somefile
EOF

Ce qui pourrait être simplifié à ceci:

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

ou:

sh -c 'touch somefile
echo foo > somefile'

Rediriger la sortie au lieu de la tuyauterie

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

Utiliser cat pour obtenir l'équivalent de echo test > out:

cat >out <<EOF
test
EOF

Plusieurs documents ici

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

Cela produit la sortie:

hi
---
there

Voici ce qui se passe:

  • Le Shell voit le ( ... ) et exécute les commandes incluses dans un sous-shell.
  • Le chat et l'écho sont assez simples. Le cat <&3 dit d'exécuter cat avec le descripteur de fichier (fd) 0 (stdin) redirigé depuis fd 3; en d'autres termes, éliminez l'entrée de fd 3.
  • Avant le (...) est démarré, le Shell voit les deux redirections et substitutions de document ici fd 0 (<<EOF) et fd 3 (3<<EOF2) avec le côté lecture des tuyaux
  • Une fois la commande initiale lancée, le Shell lit son stdin jusqu'à ce que EOF soit atteint et l'envoie au côté écriture du premier canal)
  • Ensuite, il fait de même avec EOF2 et le côté écriture du deuxième tuyau
103
ash

Je veux juste souligner que l'utilisation de meow est tout aussi valable que EOF.

Ce script ajoutera Meow! dans un fichier nommé cat:

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

Enregistrez sous cats et rendez-le exécutable avec chmod +x cats, puis exécutez-le avec ./cats:

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

Explication:

  • cat <<meow est la syntaxe ici du document . Il demande au script de récupérer le bloc de texte qui suit cette ligne, jusqu'à ce qu'il rencontre la chaîne meow. Le contenu sera ensuite sorti (ou canalisé).
  • >> cat redirige vers le fichier nommé cat.
  • En utilisant > au lieu de >> écraserait le fichier au lieu de l'ajouter.
  • Meow! est le contenu du document ici .
  • meow est le marqueur de fin du document ici . Le contenu est, avec l'utilisation de >>, ajouté à cat.

Piping à la fois vers stdout et vers un fichier:

Pour faire la tuyauterie que vous demandez, aucun document ici n'est requis.

cat ne peut pas à la fois produire du texte et transmettre le texte, mais tee correspond parfaitement à ce que vous demandez:

echo echo | tee tee

Cela produira à la fois la chaîne echo et écrit echo dans un fichier nommé tee.

Vous pouvez également transmettre la sortie via cat, si cela fait partie de l'exigence, soit avec:

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

Ou juste:

echo echo | tee tee | cat

Contenu du dossier:

$ cat tee
echo
1
Alexander