Syntaxe multiligne pour le piping d'un heredoc; est-ce portable?

132

Je connais cette syntaxe:

cmd1 << EOF | cmd2
text
EOF

mais vient de découvrir que bash me permet d'écrire:

cmd1 << EOF |
text
EOF
cmd2

(l'hérédoc est utilisé comme entrée dans cmd1 et la sortie de cmd1 est acheminée vers cmd2). Cela semble être une syntaxe très étrange. Est-ce portable?

William Pursell
la source
Je suis venu ici pour trouver un bon moyen de diviser cela en plusieurs lignes: big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. La "syntaxe étrange" semble être le meilleur moyen.
PaulC
Un cas d'utilisation pratique pour cela est lorsque vous essayez de convertir un tableau délimité par des espaces en un tableau délimité par des tabulations afin que vous puissiez le coller dans Google Spreadsheets. Vous n'aurez pas à créer de fichier temporaire.
Sridhar Sarnobat
Le premier n'a pas fonctionné pour moi dans z-shell. Je n'aime pas le 2e parce qu'il aliène le | de la commande, perdant l'idiomatie (?) des pipelines shell.
Sridhar Sarnobat

Réponses:

104

Oui, le standard POSIX le permet. Selon la version 2008:

Le document ici doit être traité comme un mot unique commençant après le suivant <newline>et se poursuivant jusqu'à ce qu'il y ait une ligne contenant uniquement le délimiteur et un <newline>, sans <blank>caractère entre les deux. Ensuite, le prochain document ici commence, s'il y en a un.

Et inclut cet exemple de plusieurs "ici-documents" dans la même ligne:

cat <<eof1; cat <<eof2
Hi,
eof1
Helene.
eof2

Il n'y a donc aucun problème à faire des redirections ou des tubes. Votre exemple est similaire à quelque chose comme ceci:

cat file |
cmd

Et la grammaire du shell (plus bas sur la page liée) comprend ces définitions:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

newline_list     :              NEWLINE
                 | newline_list NEWLINE
                 ;
linebreak        : newline_list
                 | /* empty */

Ainsi, un symbole de tuyau peut être suivi d'une fin de ligne et être toujours considéré comme faisant partie d'un pipeline.

Ned Deily
la source
26

Oui, c'est dans la grammaire du shell POSIX. Vous pouvez également avoir plus d'un here-doc pour la même commande (certains autres exemples utilisent deux catinvocations, mais cela fonctionne aussi):

cat <<EOF1 <<EOF2
first here-doc
EOF1
second here-doc
EOF2

C'est artificiel (en utilisant 2 here-docs pour stdin), mais si vous pensez à fournir une entrée pour différents descripteurs de fichiers, cela a tout de suite un sens.

Il y a aussi la possibilité de supprimer le cattout . Pourquoi ne pas rendre le document ici directement disponible pour cmd:

cmd << EOF
input
here
EOF
Jens
la source
`` cat << EOF1 << EOF2 premier ici-doc EOF1 deuxième ici-doc EOF2 `` Ce qui précède ne fonctionne pas.
user1424739
@ user1424739 Cela fonctionne dans zsh et bash actuels. Le ash et le ksh93 semblent ne sortir que le deuxième ici doc.
Jens
Pourquoi le vote négatif? S'il y a quelque chose d'inexact, donnez-moi s'il vous plaît l'occasion d'y remédier.
Jens
C'est assez gentil lors de l'utilisation sudo tee /etc/securefile.conf <<EOF.
dragon788
Sur quelle version bash ça marche? En utilisant bash 4.4.19 (sur ubuntu 18.04.02) et bash 5.0 (image docker), je n'ai obtenu que le deuxième here-doc. Ou peut-être y a-t-il une option spécifique?
huelbois
17

Hmm, je suppose que oui, d'après le test en bash en mode POSIX:

$ bash --posix
$ cat <<EOF |
> ahoj
> nazdar
> EOF
> sed 's/a/b/'
bhoj
nbzdar
TMS
la source
Juste une autre petite remarque: ne mettez aucun espace après la fermeture EOF. L'invite se comportera étrangement et vous vous demanderez ce qui ne va pas
Sridhar Sarnobat
2
Lancer bash en mode POSIX ferme certaines extensions, mais pas du tout, même presque toutes. En tant que tel, bien que cette réponse soit correcte en termes de ce que POSIX permet, son raisonnement ne le soutient pas très efficacement.
Charles Duffy
3

Bonjour, vérifiez ceci, par exemple

#!/bin/sh
( base32 -d | base64 -d )<<ENDOFTEXT
KNDWW42DNNSHS5ZXPJCG4MSVM5MVQVT2JFCTK3DELBFDCY2IIJYGE2JUJNHWS22LINVHQMCMNVFD
CWJQIIZVUV2JOVNEOVJLINTW6PIK
ENDOFTEXT

Cordialement

Buc
la source