Necesito mi script para enviar un correo electrónico desde la terminal. Basado en lo que he visto aquí y en muchos otros lugares en línea, lo formateé así:
/var/mail -s "$SUBJECT" "$EMAIL" << EOF
Here's a line of my message!
And here's another line!
Last line of the message here!
EOF
Sin embargo, cuando ejecuto esto, aparece esta advertencia:
myfile.sh: line x: warning: here-document at line y delimited by end-of-file (wanted 'EOF')
myfile.sh: line x+1: syntax error: unexpected end of file
... donde la línea x es la última línea de código escrita en el programa, y la línea y es la línea que /var/mail
contiene. He intentado reemplazar EOF
con otras cosas ( ENDOFMESSAGE
, FINISH
, etc.), pero en vano. Casi todo lo que he encontrado en línea lo ha hecho de esta manera, y soy realmente nuevo en bash, por lo que me está costando descubrirlo por mi cuenta. ¿Alguien podría ofrecer alguna ayuda?
EOF
línea tiene sangría? Tiene que estar al principio de la línea.<<-EOF
- gnu.org/software/bash/manual/bashref.html#Here-DocumentsRespuestas:
El
EOF
token debe estar al principio de la línea, no puede sangrarlo junto con el bloque de código al que va.Si escribe
<<-EOF
, puede sangrarlo, pero debe hacerlo con Tabcaracteres, no con espacios. Por lo tanto, es posible que aún no termine ni siquiera con el bloque de código.También asegúrese de no tener espacios en blanco después del
EOF
token en la línea.fuente
dos2unix
para solucionarlo.La línea que comienza o termina aquí-doc probablemente tiene algunos caracteres no imprimibles o de espacio en blanco (por ejemplo, retorno de carro) lo que significa que el segundo "EOF" no coincide con el primero, y no termina el here-doc como debería. Este es un error muy común y difícil de detectar con solo un editor de texto. Puede hacer visibles los caracteres no imprimibles, por ejemplo, con
cat
:Una vez que vea el resultado de
cat -A
la solución, será obvio: elimine los caracteres ofensivos.fuente
Intente eliminar los espacios anteriores antes de
EOF
: -/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF
Usar en
<tab>
lugar de<spaces>
para ident Y usar << - EOF funciona bien.El
"-"
quita el<tabs>
, no<spaces>
, pero al menos funciona este.fuente
Tenga en cuenta que también se puede obtener este error si hace esto;
while read line; do echo $line done << somefile
Porque
<< somefile
debería leerse< somefile
en este caso.fuente
Esta es una forma flexible de tratar con múltiples líneas con sangría sin usar heredoc.
echo 'Hello!' sed -e 's:^\s*::' < <(echo ' Some indented text here. Some indented text here. ') if [[ true ]]; then sed -e 's:^\s\{4,4\}::' < <(echo ' Some indented text here. Some extra indented text here. Some indented text here. ') fi
Algunas notas sobre esta solución:
\
o reemplace los delimitadores de cadena con comillas dobles. En el último caso, tenga cuidado de que$(command)
se interprete la construcción como . Si la cadena contiene comillas simples y dobles, tendrá que escapar al menos del tipo.fuente
Cuando quiero tener docstrings para mis funciones de bash, uso una solución similar a la sugerencia de user12205 en un duplicado de esta pregunta.
Vea cómo defino USO para una solución que:
function foo { # Docstring read -r -d '' USAGE <<' END' # This method prints foo to the terminal. # # Enter `foo -h` to see the docstring. # It has indentations and multiple lines. # # Change the delimiter if you need hashtag for some reason. # This can include $$ and = and eval, but won't be evaluated END if [ "$1" = "-h" ] then echo "$USAGE" | cut -d "#" -f 2 | cut -c 2- return fi echo "foo" }
Entonces
foo -h
rinde:This method prints foo to the terminal. Enter `foo -h` to see the docstring. It has indentations and multiple lines. Change the delimiter if you need hashtag for some reason. This can include $$ and = and eval, but won't be evaluated
Explicación
cut -d "#" -f 2
: Recupera la segunda parte de las#
líneas delimitadas. (Piense en un csv con "#" como delimitador, la primera columna vacía).cut -c 2-
: Recupera el segundo carácter al final de la cadena resultanteTambién tenga en cuenta que se
if [ "$1" = "-h" ]
evalúa comoFalse
si no hubiera un primer argumento, sin error, ya que se convierte en una cadena vacía.fuente
Junto con las otras respuestas mencionadas por Barmar y Joni, he notado que a veces tengo que dejar una línea en blanco antes y después de mi EOF cuando lo uso
<<-EOF
.fuente
cat
varias líneas envuelto en parens para redirigir y debido al formato, justo antes de cerrar el marcador here-doc, necesitaba agregar una entrada antes de los parientes de cierre, de lo contrario, obtendría esta falta de coincidencia. La votación a favor es completamente válida para "algunas" personas, aunque probablemente sea un escenario poco probable.