Est-il possible d'utiliser plusieurs here-docs dans bash?

14

Peut-on utiliser plusieurs here-docs pour fournir une entrée à une commande dans bash?

$ cat <<<foo <<<bar
bar
$ cat <<EOF1 <<EOF2
> foo
> EOF1
> bar
> EOF2
bar

Évidemment, dans les deux cas, le second here-doc est utilisé comme stdin, et remplace la première référence. La solution consiste-t-elle à utiliser echos à la place?

$ cat <(echo -n foo) <(echo bar)
foobar

De plus, pour une raison quelconque, l'utilisation d'une combinaison n'a pas fonctionné pour moi. Pourquoi serait-ce?

$ cat <<<foo <(echo bar)
bar
$ cat <(echo -n foo) <<<bar
foo
Sparhawk
la source
Y a-t-il une raison derrière le fait que vous souhaitez utiliser deux documents ici plutôt que de les combiner en un seul?
haricots
1
@beans Je l'ai rencontré lors de tests pasteavec des entrées factices. Je suppose que je peux penser à quelques autres scénarios. Si j'avais eu un script avec du texte pré-manipulé dans quelques variables, alors je pourrais vouloir faire quelque chose aux deux avec une commande qui ne prend que des fichiers, par exemple diff.
Sparhawk
Un autre cas d' utilisation (j'ai trouvé cela en utilisant ici-docs pour créer un script shell): vous voulez quelques lignes avec l' expansion variable, puis quelques lignes sans: cat <<EOF1 <<"EOF2".
Toby Speight

Réponses:

18

Tu peux faire:

cat /dev/fd/3 3<< E1 /dev/fd/4 4<< E2
foo
E1
bar
E2

Il ne peut y avoir qu'un seul stdin, car il n'y a qu'un seul descripteur de fichier 0.

cat << EOF
eof
EOF

est l'abréviation de:

cat /dev/fd/0 0<< EOF
eof
EOF

Et:

cat <<< foo

est:

cat /dev/fd/0 0<<< foo

Vous devez décider quoi ouvrir sur le descripteur de fichier 0.

cat <(echo foo)

Est:

cat /dev/fd/123

123est un descripteur de fichier pour un canal, et en parallèle, bash s'exécute echo foodans un autre processus avec la sortie standard redirigée vers l'autre extrémité du canal.

Une fois que vous avez passé un nom de fichier à cat, catne lisez plus depuis stdin. Vous auriez besoin de:

cat <(echo foo) /dev/fd/0 << EOF
bar
EOF

Ou:

cat <(echo foo) - << EOF
bar
EOF

( -c'est dire catde lire depuis stdin).

Stéphane Chazelas
la source
1
cat <<EOFn'est pas exactement le même que cat /dev/fd/0...: dans ce dernier cas catvoit le nom du fichier et fait l'ouvrir.
Mikel
@Mikel, ce que je voulais dire, c'est qu'il est fonctionnellement équivalent . Lorsqu'aucun argument n'est passé, catlit à partir de son fd0, comme s'il avait passé un argument de -ou /dev/fd/0(bien que sur Linux (et Linux uniquement), l'ouverture /dev/fd/0ne ressemble pas exactement à la duplication du descripteur de fichier 0).
Stéphane Chazelas
J'ai été très surpris par la /dev/fd/3 3<< E1construction et je me demande maintenant ce que sont exactement les éléments sous / dev / fd /. Je pense qu'ils semblent en quelque sorte magiques après que le processus ouvre un fichier quelque part sur le système de fichiers à l'exception de 1 et 2 qui sont là par défaut pour chaque processus. Mais dans votre exemple, vous utilisez les descripteurs de fichiers 3 et 4 qui ne sont connectés à aucun fichier réel, à l'exception de cette redirection d'entrée. Je ne peux pas comprendre cela dans mon modèle mental de descripteurs de fichiers. Que faire si le processus souhaite ouvrir un autre fichier, saura-t-il qu'il doit utiliser fd 5? Les fds doivent-ils être 3, 4, 5 .. ou peuvent être n'importe quoi?
calavera.info
@ calavera.info, il semble que vous souhaitiez créer une question de suivi.
Stéphane Chazelas