No se puede sangrar heredoc para que coincida con la sangría de anidamiento


62

Si hay un "First World Problems" para las secuencias de comandos, este sería el problema.

Tengo el siguiente código en un script que estoy actualizando:

if [ $diffLines -eq 1 ]; then
        dateLastChanged=$(stat --format '%y' /.bbdata | awk '{print $1" "$2}' | sed 's/\.[0-9]*//g')

        mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<EOI
        Last Change: $dateLastChanged

        This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
EOI

else
        echo "$diffLines have changed"
fi

El script envía correos electrónicos sin problemas, pero el comando mailx está anidado dentro de una instrucción if, por lo que parece que me quedan dos opciones:

  1. Poner EOIuna nueva línea y romper patrones de sangría o
  2. Mantenga la sangría pero use algo como una declaración de eco para que mailx absorba mi correo electrónico.

Estoy abierto a alternativas al heredoc, pero si hay una forma de evitar esto, es mi sintaxis preferida.

Respuestas:


113

Puede cambiar el operador here-doc a <<-. Luego puede sangrar tanto el here-doc como el delimitador con pestañas:

#! /bin/bash
cat <<-EOF
    indented
    EOF
echo Done

Tenga en cuenta que debe usar pestañas , no espacios para sangrar el documento aquí. Esto significa que el ejemplo anterior no funcionará copiado (Stack Exchange reemplaza las pestañas con espacios). No puede haber comillas alrededor del primer EOFdelimitador, de lo contrario, la expansión de parámetros, la sustitución de comandos y la expansión aritmética no están vigentes.


Genial, eso soluciona el problema de sangría, pero ahora no está expandiendo la variable que estoy tratando de poner allí ( $dateLastChanged) si hago lo de las comillas de hypen + en su ejemplo, pero si tomo el guión y las citas y pongo EOI en un nueva línea comienza a expandirse nuevamente.
Bratchley

1
@JoelDavis: solo elimine las comillas, guarde el guión.
choroba

55
Ser obligado a usar pestañas es muy molesto. ¿Hay alguna forma de evitarlo?
con-f-use

2
@ con-f-use: puede probar algo así, cat << EOF | sed 's/^ *//'etc.
choroba

44
O aún mejor: cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. Esto elimina la cantidad de espacios anteriores en la primera línea de cada línea en el documento aquí (gracias a anubhava ).
con-f-use

5

Si no necesita la sustitución de comandos y la expansión de parámetros dentro de su documento aquí, puede evitar el uso de pestañas agregando los espacios iniciales al delimitador:

$     cat << '    EOF'
>         indented
>     EOF
        indented
$     cat << '    EOF' | sed -r 's/^ {8}//'
>         unindented
>     EOF
unindented

Sin embargo, no pude encontrar una manera de usar este truco y mantener la expansión de parámetros.


1
Para mí, esta es la única respuesta que resuelve el problema de sangría sin usar espacios. shell-checkencontrará cualquier cambio de sangría que no coincida con los espacios en la cadena entre comillas. ¿Usar comillas dobles para la expansión de parámetros?
Tom Hale

4

Prueba esto:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF

No puede tener líneas con sangría diferente dentro del heredoc en este caso. (Esto importa si, por ejemplo, el contenido es un script.)
ivan_pozdeev

2

Hmm ... Parece que podrías aprovechar mejor el --formatargumento aquí para usar --printfen su lugar y simplemente pasar el lote por una tubería. Además, su if...fies un comando compuesto: puede tomar una redirección que heredarán todos los comandos contenidos, por lo que tal vez no necesite anidar el heredoc en absoluto.

if      [ "$diffLines" = 1 ]
then    stat --printf "Last Change: %.19y\n\n$(cat)\n" /.bbdata |
        mailx   -r  "Systems and Operations <sysadmin@[redacted].edu>" \
                -s  "Warning Stale BB Data" 'jadavis6@[redacted].edu'
else    echo    "$diffLines have changed"
fi      <<\STALE
This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
STALE

Sí, mi revisión anterior dijo que no me importaba el sed/ awkparte. Parte de mi revisión de hoy fue sacarlo ya que no estaba relacionado con la pregunta. De cualquier manera, son seis de media docena de la otra.
Bratchley

@Bratchley - maldita sea. Esa última oración me va a distraer por el resto del día.
mikeserv

¿A qué te refieres?
Bratchley

1
@Bratchley - Parece un acertijo.
mikeserv

Decir ah. No estoy seguro de qué país eres, pero esa es una frase común en los Estados Unidos. Simplemente significa "Enfoque diferente para el mismo fin". Sin embargo, su solución se mueve por aquí.
Bratchley

0

El otro método serían las herejías:

    mail_content="Last Change: $dateLastChanged

    This is an automated warning of stale data for the UNC-G Blackboard Snapshot process."
    mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<<"$mail_content"
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.