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

56

Disons que j'ai un script que je veux diriger vers une autre commande ou rediriger vers un fichier (la tuyauterie à shpour 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", cela signifie simplement que cela fait partie de l'heredoc.

Comment puis-je faire en sorte que le cattexte en sortie de stdin, puis le dirige vers un emplacement quelconque?

combattant
la source
touchest à moins que, que voulez-vous exactement? est juste de lire le fichier d'entrée et de rediriger vers un autre avec stdout?
Rahul Patil
2
@RahulPatil bien sûr que c'est inutile. Je voulais juste un exemple avec plus d'une ligne, pour mieux illustrer l'hérédoc. Et regardez l'exemple utilisant echo- je me demandais quel serait l'équivalent de cela cat.
Strugee
Votre exemple consiste à créer un shscript à partir de plusieurs chaînes et à le transmettre directement à sh. J'ai trouvé votre Q cherchant à transmettre le texte de plusieurs commandes, y compris un document HERE, directement à une commande. C'est ce que fait le deuxième exemple de la réponse de Ash.
Dave X

Réponses:

91

Il y a plusieurs façons de le faire. Le plus simple est probablement ceci:

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

Une autre, qui est la syntaxe plus agréable à mon avis:

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

Cela fonctionne aussi, 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

En passant, je suppose que l'utilisation de catvotre question est un espace réservé pour autre chose. Sinon, sortez-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 catpour 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

Ceci 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 <&3dit de lancer un chat avec un descripteur de fichier (fd) 0 (stdin) redirigé depuis fd 3; autrement dit, supprimez l’entrée de fd 3.
  • Avant que ne (...)soit lancé, le shell voit ici les deux redirections de document et substitue fd 0 ( <<EOF) et fd 3 ( 3<<EOF2) par le côté lecture des tuyaux
  • Une fois la commande initiale lancée, le shell lit son stdin jusqu'à atteindre EOF et l'envoie au côté écriture du premier canal
  • Ensuite, il en va de même avec EOF2 et le côté écriture du second tube
cendre
la source
étant donné l'avant-dernier exemple, pouvez-vous donner un exemple avec la redirection stdout au lieu de la tuyauterie?
Strugee
J'ai édité la réponse avec un exemple de redirection; est-ce que c'est le formulaire que vous vouliez édité? Si non, pouvez-vous simplement donner la première ligne de cette partie pour clarifier?
cendres
1
Il peut être utile de comprendre comment le shell traite cela. Lorsqu'il évalue la ligne de commande et trouve le << EOF, il lit ensuite à partir de l'entrée standard jusqu'à ce qu'une ligne contenant uniquement EOF soit trouvée ou la fin de l'entrée. Tout le reste de la ligne de commande d'origine qui n'a pas encore été traité continue à être traité. Ainsi, par exemple, il est possible de faire quelque chose comme ceci: (cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >outet ensuite donner cette entrée de commande avec deux here-blocks dans une rangée.
cendres
Votre explication sur le traitement des coques était intéressante, mais au-dessus de ma tête :) Ce que je voulais savoir, c’était l’ catéquivalent de ce qui serait équivalent echo test > out, en utilisant un heredoc. Considérant que votre exemple donné a ajouté une redirection à la fin du tuyau.
Strugee
1
@OlivierDulac - J'ai ajouté l'exemple Heredoc multiple à la réponse.
cendres
1

Je veux juste souligner que l'utilisation meowest tout aussi valable que EOF.

Ce script va ajouter Meow!à un fichier nommé cat:

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

Enregistrer sous catset le rendre exécutable avec chmod +x cats, puis exécutez-le avec ./cats:

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

Explication:

  • cat <<meowest la syntaxe ici du document . Il demande au script de saisir le bloc de texte qui suit cette ligne jusqu'à ce qu'il rencontre la chaîne meow. Le contenu sera alors sorti (ou transmis).
  • >> cattuyaux vers le fichier nommé cat.
  • Utiliser >au lieu de >>remplacer écraserait le fichier au lieu de l'ajouter.
  • Meow!est le contenu du document ici .
  • meowest le marqueur de fin pour le 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.

catne peut pas à la fois produire du texte et le transmettre, mais teecorrespond parfaitement à ce que vous demandez:

echo echo | tee tee

Cela va à la fois sortir la chaîne echoet écrire echodans un fichier nommé tee.

Vous pouvez également transmettre la sortie 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
Alexandre
la source
1
Cela ne répond pas vraiment à la question. En outre, >ne crée pas de tuyaux comme votre dernière puce implique.
Strugee
2
@strugee, >peut créer des pipes zshlorsque le même fd est redirigé plusieurs fois, comme dans echo foo >&1 > teeou echo foo > tee | cat, où zshimplémente un interne teepour alimenter la sortie des echodeux catet du teefichier.
Stéphane Chazelas
Mise à jour ma réponse pour mieux répondre à la question.
Alexander