Heredoc ne peut pas indenter pour correspondre à l'indent de nidification

62

S'il y a un "First World Problems" pour le script, ce serait bien.

J'ai le code suivant dans un script que je mets à jour:

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

Le script envoie un courrier électronique sans problème, mais la commande mailx est imbriquée dans une instruction if. Il semble donc que je dispose de deux choix:

  1. Mettez EOIune nouvelle ligne et brisez les motifs d’indentation ou
  2. Conservez-le avec indentation mais utilisez quelque chose comme une déclaration echo pour que mailx suce mon courrier électronique.

Je suis ouvert aux alternatives à heredoc, mais s'il existe un moyen de contourner cela, c'est ma syntaxe préférée.

Bratchley
la source

Réponses:

113

Vous pouvez changer l'opérateur here-doc en <<-. Vous pouvez alors indenter à la fois le here-doc et le délimiteur avec des onglets:

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

Notez que vous devez utiliser des tabulations , pas des espaces pour indenter le here-doc. Cela signifie que l'exemple ci-dessus ne fonctionnera pas copié (Stack Exchange remplace les onglets par des espaces). Il ne peut y avoir de guillemets autour du premier EOFdélimiteur, sinon le développement des paramètres, la substitution de commande et le développement arithmétique ne sont pas effectifs.

choroba
la source
Cool, ça résout le problème de retrait mais maintenant cela $dateLastChangedn’élargit pas la variable que j’essaie de mettre dedans ( ) si je fais la chose hypen + quotes dans votre exemple, mais si je prends le trait d’union et cite et mets EOI sur un nouvelle ligne, il recommence à l'agrandir.
Bratchley
1
@JoelDavis: Il suffit de supprimer les guillemets, de conserver le trait d'union.
Choroba
5
Être obligé d'utiliser des tabulations est très ennuyant. Y a-t-il un bon moyen de le contourner?
con-f-use
2
@ con-f-use: Vous pouvez essayer quelque chose comme cat << EOF | sed 's/^ *//'et ainsi de suite.
Choroba
4
Ou mieux encore: cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. Cela supprime la quantité d'espaces précédents de la première ligne de chaque ligne du document here (grâce à anubhava ).
con-f-use
5

Si vous n'avez pas besoin de substitution de commande ni de développement de paramètres dans votre document here, vous pouvez éviter d'utiliser des tabulations en ajoutant les espaces de début au délimiteur:

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

Je ne pouvais pas trouver un moyen d'utiliser cette astuce et garder l'expansion des paramètres, cependant.

Itsadok
la source
1
Pour moi, c'est la seule réponse qui résout le problème d'indentation sans utiliser d'espaces. shell-checktrouvera toute modification d’indentation qui ne correspond pas aux espaces de la chaîne citée. Utilisez les guillemets doubles pour développer les paramètres?
Tom Hale
4

Essaye ça:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF
robz
la source
Dans ce cas, vous ne pouvez pas avoir de lignes indentées différemment dans l'hérédoc. (Ceci est important si, par exemple, le contenu est un script.)
ivan_pozdeev
2

Hmm ... On dirait que vous pourriez mieux tirer parti de l' --formatargument présenté ici pour utiliser --printfplutôt que de passer le tout au-dessus d'un tuyau. En outre, votre if...ficommande est composée - elle peut prendre une redirection dont toutes les commandes contenues hériteront. Vous n'avez donc peut-être pas besoin d'imbriquer l'hérédoc.

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
Mikeserv
la source
Oui, ma précédente révision disait que la partie sed/ ne me dérangeait pas awk. Une partie de ma révision d’aujourd’hui consistait à le supprimer car cela n’était pas lié à la question. De toute façon, il est six d'une demi-douzaine de l'autre.
Bratchley
@Bratchley - zut. Cette dernière phrase va me distraire pour le reste de la journée.
mikeserv le
Qu'est-ce que vous voulez dire?
Bratchley
1
@Bratchley - On dirait une énigme.
mikeserv le
Ha. Vous ne savez pas de quel pays vous venez mais c'est une expression courante aux États-Unis. Cela signifie simplement "une approche différente dans le même but". Votre solution contourne cependant Heredoc.
Bratchley
0

L'autre méthode serait herestrings:

    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"
muru
la source