809 votes

Comment fonctionne "cat << EOF" dans bash?

J'avais besoin d'écrire un script pour entrer une entrée multi-ligne dans un programme (psql).

Après un peu de recherche sur Google, j'ai trouvé que la syntaxe suivante fonctionne :

cat << EOF | psql ---params
BEGIN;

`pg_dump ----something`

update table .... statement ...;

END;
EOF

Cela construit correctement la chaîne multi-ligne (de BEGIN; à END;, inclusivement) et la passe en tant qu'entrée à psql.

Mais je n'ai aucune idée de comment/pourquoi cela fonctionne, quelqu'un pourrait-il s'il vous plaît expliquer?

Je fais principalement référence à cat << EOF, je sais que > écrit dans un fichier, >> ajoute à un fichier, < lit une entrée depuis un fichier.

Que fait exactement <<?

Et y a-t-il une page de manuel à ce sujet?

34 votes

C'est probablement une utilisation inutile de cat. Essayez psql ... << EOF ... Voir aussi "here strings". mywiki.wooledge.org/BashGuide/InputAndOutput?#Here_Strings

1 votes

Je suis surpris que cela fonctionne avec cat mais pas avec echo. cat devrait s'attendre à un nom de fichier en tant que stdin, pas une chaîne de caractères. psql << EOF semble logique, mais pas autrement. Fonctionne avec cat mais pas avec echo. Comportement étrange. Une idée à ce sujet ?

0 votes

En me répondant : chat sans paramètres exécute et réplique en sortie tout ce qui est envoyé via l'entrée (stdin), utilisant ainsi sa sortie pour remplir le fichier via >. En fait, un nom de fichier lu comme un paramètre n'est pas un flux stdin.

12voto

Lefty G Balogh Points 762

Une petite extension aux réponses ci-dessus. Le > final dirige l'entrée dans le fichier, écrasant le contenu existant. Cependant, une utilisation particulièrement pratique est la double flèche >> qui ajoute, ajoutant votre nouveau contenu à la fin du fichier, comme ceci:

cat <> /etc/fstab
data_server:/var/sharedServer/authority/cert /var/sharedFolder/sometin/authority/cert nfs
data_server:/var/sharedServer/cert   /var/sharedFolder/sometin/vsdc/cert nfs
EOF

Cela étend votre fstab sans que vous ayez à vous soucier de modifier accidentellement l'un de ses contenus.

4voto

yuranos87 Points 1371

En résumé, le marqueur EOF (mais un littéral différent peut également être utilisé) est un format heredoc qui vous permet de fournir votre saisie sur plusieurs lignes. Beaucoup de confusion vient de la façon dont cat fonctionne en fait. Vous pouvez utiliser cat avec >> ou > de la manière suivante :

$ cat >> temp.txt
line 1
line 2

Alors que cat peut être utilisé de cette manière lors de la saisie manuelle dans la console, ce n'est pas pratique si je veux fournir la saisie de manière plus déclarative afin qu'elle puisse être réutilisée par des outils et aussi pour conserver les indentations, les espaces, etc.
Heredoc permet de définir toute votre saisie comme si vous ne travailliez pas avec stdin mais que vous tapiez dans un éditeur de texte séparé. C'est ce que l'article de Wikipedia signifie par :

c'est une section d'un fichier source qui est traitée comme si c'était un fichier séparé.

4voto

Chris Halcrow Points 907

<< EoF signifie en gros :

<< - "lire l'entrée multi-ligne qui commence à partir de la ligne suivante, et la traiter comme si c'était du code dans un fichier séparé"

EoF - "arrêter la lecture immédiatement après que le mot EoF soit trouvé dans l'entrée multi-ligne"

Comme d'autres réponses l'ont expliqué, l'entrée multi-ligne est appelée un Here Document (c'est-à-dire un document qui est fourni 'en ligne' ou 'sur place').

Un Here Document est souvent utilisé pour générer une sortie à transmettre à un processus ultérieur. Par exemple, cat << EoF peut être utilisé pour générer une sortie souhaitée, en utilisant un Here Document.

Voici un exemple d'utilisation d'un Here Document pour créer un document texte à la volée :

cat << EoF > ./mon-document.txt
Bonjour le monde
Passe une bonne journée
EoF

1voto

Ce n'est pas nécessairement une réponse à la question initiale, mais un partage de quelques résultats de mes propres tests. Ceci :

< print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

produira le même fichier que :

cat < print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

Donc, je ne vois pas l'intérêt d'utiliser la commande cat.

2 votes

Quel shell ? J'ai testé avec bash 4.4 sur Ubuntu 18.04 ainsi que bash 3.2 sur OSX. Les deux ont créé un fichier vide en utilisant simplement < sans `cat <.`

1voto

dwi kristianto Points 6

Note à mentionner que cat << \EOT (voir le backslash) n'expandra aucune variable à l'intérieur, tandis que cat << EOT le fera.

exemples:

FOO="bar"

cat << \EOT > foobar.txt
echo "$FOO"
EOT

produira: echo $FOO

alors que:

FOO="bar"

cat << EOT > foobar.txt
echo "$FOO"
EOT

produira: echo "bar"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X