Sintaxis multilínea para canalizar un heredoc; ¿Es esto portátil?


132

Estoy familiarizado con esta sintaxis:

cmd1 << EOF | cmd2
text
EOF

pero acabo de descubrir que bash me permite escribir:

cmd1 << EOF |
text
EOF
cmd2

(el heredoc se usa como entrada para cmd1, y la salida de cmd1 se canaliza a cmd2). Esto parece una sintaxis muy extraña. ¿Es portátil?


He venido aquí para encontrar una buena manera de dividir esta en varias líneas: big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. La "sintaxis impar" parece ser la mejor manera.
PaulC

Un caso de uso conveniente para esto es cuando intentas convertir una tabla delimitada por espacios en una delimitada por tabulaciones para que puedas pegarla en las hojas de cálculo de Google. No tendrá que crear un archivo temporal.
Sridhar Sarnobat

El primero no funcionó para mí en z-shell. No me gusta el segundo porque aliena al | del comando, perdiendo la idiotez (?) de las tuberías de concha.
Sridhar Sarnobat

Respuestas:


104

Sí, el estándar POSIX lo permite. Según la versión 2008:

El documento aquí se tratará como una sola palabra que comienza después de la siguiente <newline>y continúa hasta que haya una línea que contenga solo el delimitador y a <newline>, sin <blank>caracteres intermedios. Entonces comienza el siguiente documento aquí, si hay uno.

E incluye este ejemplo de múltiples "documentos aquí" en la misma línea:

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

Por lo tanto, no hay problema para hacer redirecciones o tuberías. Su ejemplo es similar a algo como esto:

cat file |
cmd

Y la gramática del shell (más abajo en la página vinculada) incluye estas definiciones:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

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

Por lo tanto, un símbolo de tubería puede ir seguido de un final de línea y aún así considerarse parte de una tubería.


26

Sí, está en la gramática de shell POSIX. También puede tener más de un documento aquí para el mismo comando (algunos otros ejemplos usan dos catinvocaciones, pero esto también funciona):

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

Esto es artificial (usando 2 here-docs para stdin), pero si piensa proporcionar información para diferentes descriptores de archivo, tiene sentido de inmediato.

También existe la posibilidad de soltarlo por catcompleto . ¿Por qué no hacer que el documento aquí esté directamente disponible para cmd:

cmd << EOF
input
here
EOF

`` `cat << EOF1 << EOF2 primero here-doc EOF1 segundo here-doc EOF2` `` Lo anterior no funciona.
user1424739

@ user1424739 Funciona en zsh y bash actuales. El ash y el ksh93 parecen emitir solo el segundo documento aquí.
Jens

¿Por qué el voto negativo? Si hay algo impreciso, por favor dame la oportunidad de remediarlo.
Jens

Esto es bastante dulce cuando se usa sudo tee /etc/securefile.conf <<EOF.
dragon788

¿En qué versión bash funciona? Usando bash 4.4.19 (en ubuntu 18.04.02) y bash 5.0 (imagen acoplable), solo obtuve el segundo documento aquí. ¿O tal vez hay una opción específica?
huelbois

17

Hmm, supongo que sí, de acuerdo con la prueba en bash en modo POSIX:

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

Solo otra pequeña nota: no ponga ningún espacio después del cierre EOF. El mensaje se comportará de manera extraña y te preguntarás qué demonios está mal
Sridhar Sarnobat el

2
Ejecutar bash en modo POSIX cierra algunas extensiones, pero no de ninguna manera, ni siquiera en casi todas. Como tal, si bien esta respuesta es correcta en términos de lo que POSIX permite, su razonamiento no lo admite de manera muy efectiva.
Charles Duffy el

3

Hola, mira esto, por ejemplo

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

Saludos

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.