Não é possível recuar o heredoc para corresponder ao recuo do aninhamento

62

Se houver um "Problemas do Primeiro Mundo" para scripts, seria esse.

Eu tenho o seguinte código em um script que estou atualizando:

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

O script envia email sem problemas, mas o comando mailx está aninhado em uma instrução if, portanto, pareço ter duas opções:

  1. Coloque EOIuma nova linha e quebre os padrões de indentação ou
  2. Mantenha o recuo, mas use algo como uma declaração de eco para obter o mailx para sugar o meu email.

Estou aberto a alternativas ao heredoc, mas se houver uma maneira de contornar isso, é a minha sintaxe preferida.

Bratchley
fonte

Respostas:

113

Você pode alterar o operador aqui-doc para <<-. Em seguida, você pode recuar o documento aqui e o delimitador com guias:

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

Observe que você deve usar guias , não espaços para recuar o documento aqui. Isso significa que o exemplo acima não funcionará copiado (o Stack Exchange substitui as guias por espaços). Não pode haver aspas ao redor do primeiro EOFdelimitador; caso contrário, a expansão de parâmetros, a substituição de comandos e a expansão aritmética não estão em vigor.

choroba
fonte
Legal, isso resolve o problema do recuo, mas agora não está expandindo a variável que estou tentando colocar lá ( $dateLastChanged) se eu fizer a coisa hypen + quote no seu exemplo, mas se eu pegar o hífen e as aspas e colocar EOI em um nova linha ele começa a expandi-lo novamente.
Bratchley
11
@ JoelDavis: Basta remover as aspas, manter o hífen.
#
5
Ser forçado a usar guias é muito irritante. Existe uma boa maneira de contornar isso?
con-f-use
2
@ con-f-use: Você pode tentar algo assim cat << EOF | sed 's/^ *//'e assim por diante.
#
4
Ou melhor ainda: cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. Isso remove a quantidade de espaços anteriores na primeira linha de todas as linhas do documento aqui (graças ao anubhava ).
con-f-use
5

Se você não precisar de substituição de comando e expansão de parâmetro no documento aqui, poderá evitar o uso de guias adicionando os espaços iniciais ao delimitador:

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

Mas não consegui descobrir uma maneira de usar esse truque e manter a expansão dos parâmetros.

itsadok
fonte
11
Para mim, esta é a única resposta que resolve o problema do recuo sem usar espaços. shell-checkencontrará alterações de recuo que não correspondam aos espaços na cadeia de caracteres citada. Use aspas duplas para a expansão de parâmetros?
Tom Hale
4

Tente o seguinte:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF
Robz
fonte
Você não pode ter linhas com recuos diferentes dentro do heredoc, neste caso. (Isso importa se, por exemplo, o conteúdo for um script.)
ivan_pozdeev
2

Hmm ... Parece que você poderia aproveitar melhor o --formatargumento aqui para usar --printfe apenas passar o lote por um cano. Além disso, você if...fié um comando composto - pode ser necessário um redirecionamento que todos os comandos contidos herdarão, portanto, talvez você não precise aninhar o heredoc.

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
fonte
Sim minha revisão anterior disse que não se importava com o sed/ awkparte. Parte da minha revisão hoje foi removê-la, pois não era pertinente à questão. De qualquer maneira, são seis de meia dúzia da outra.
Bratchley
@Bratchley - caramba. Essa última frase vai me distrair pelo resto do dia.
mikeserv
O que você quer dizer?
Bratchley
11
@Bratchley - Parece um enigma.
mikeserv
Ha. Não sei de que país você é, mas é uma frase comum nos Estados Unidos. Apenas significa "abordagem diferente para o mesmo fim". Sua solução contorna o heredoc.
Bratchley 27/01
0

O outro método seria 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
fonte