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.

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.


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.


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

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

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"
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.