Sintassi multilinea per il piping di un ereditario; è portatile?


132

Conosco questa sintassi:

cmd1 << EOF | cmd2
text
EOF

ma ho appena scoperto che bash mi permette di scrivere:

cmd1 << EOF |
text
EOF
cmd2

(l'ereditarietà viene utilizzata come input per cmd1 e l'output di cmd1 viene reindirizzato a cmd2). Sembra una sintassi molto strana. È portatile?


Sono venuto qui per trovare un buon modo di dividere questo in più righe: big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. La "sintassi dispari" sembra il modo migliore.
PaulC

Un comodo caso d'uso per questo è quando stai cercando di convertire una tabella delimitata da spazi in una delimitata da tabulazioni in modo da poterla incollare in Fogli di lavoro Google. Non dovrai creare un file temporaneo.
Sridhar Sarnobat,

Il primo non ha funzionato per me in z-shell. Non mi piace il secondo perché aliena il | dal comando, perdendo l'idioma (?) delle pipeline di shell.
Sridhar Sarnobat,

Risposte:


104

Sì, lo standard POSIX lo consente. Secondo la versione 2008:

Il documento qui deve essere trattato come una singola parola che inizia dopo la successiva <newline>e continua fino a quando non vi è una riga contenente solo il delimitatore e una <newline>, senza <blank>caratteri in mezzo. Quindi inizia il prossimo documento qui, se ce n'è uno.

E include questo esempio di più "documenti qui" nella stessa riga:

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

Quindi non ci sono problemi a fare reindirizzamenti o pipe. Il tuo esempio è simile a qualcosa del genere:

cat file |
cmd

E la grammatica della shell (più in basso nella pagina collegata) include queste definizioni:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

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

Quindi un simbolo di tubo può essere seguito da un fine linea ed essere comunque considerato parte di una conduttura.


26

Sì, è nella grammatica della shell POSIX. Puoi anche avere più di un qui-doc per lo stesso comando (alcuni altri esempi usano due catinvocazioni, ma funziona anche):

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

Questo è inventato (usando 2 here-docs per stdin), ma se pensi di fornire input per diversi descrittori di file ha immediatamente senso.

C'è anche la possibilità di eliminare catcompletamente . Perché non rendere il documento qui direttamente disponibile per cmd:

cmd << EOF
input
here
EOF

`` cat << EOF1 << EOF2 prima qui-doc EOF1 seconda qui-doc EOF2 `` `Quanto sopra non funziona.
user1424739

@ user1424739 Funziona con zsh e bash attuali. Il ash e il ksh93 sembrano produrre solo il secondo qui doc.
Jens,

Perché il downvote? Se c'è qualcosa di inaccurato, per favore dammi l'opportunità di rimediare.
Jens,

Questo è piuttosto dolce quando si usa sudo tee /etc/securefile.conf <<EOF.
dragon788,

Su quale versione bash funziona? Usando bash 4.4.19 (su Ubuntu 18.04.02) e bash 5.0 (immagine docker), ho ottenuto solo il secondo qui-doc. O forse c'è un'opzione specifica?
huelbois,

17

Hmm, suppongo di sì, secondo il test in bash in modalità POSIX:

$ bash --posix
$ cat <<EOF |
> ahoj
> nazdar
> EOF
> sed 's/a/b/'
bhoj
nbzdar

Solo un'altra piccola nota: non mettere spazi dopo la chiusura EOF. Il prompt si comporterà in modo strano e ti chiederai che diavolo c'è di sbagliato
Sridhar Sarnobat,

2
L'esecuzione di bash in modalità POSIX arresta alcune estensioni, ma non in alcun modo nemmeno quasi tutte. Pertanto, sebbene questa risposta sia corretta in termini di ciò che POSIX consente, il suo ragionamento non lo supporta in modo molto efficace.
Charles Duffy,

3

Ciao, controlla questo, per esempio

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

Saluti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.