Tidak dapat membuat indentasi heredoc untuk mencocokkan indentasi sarang

62

Jika ada "Masalah Dunia Pertama" untuk scripting, ini dia.

Saya memiliki kode berikut dalam skrip yang saya perbarui:

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

Script mengirim email tanpa masalah, tetapi perintah mailx bersarang di dalam pernyataan if jadi saya tampaknya dibiarkan dengan dua pilihan:

  1. Letakkan EOIdi baris baru dan pecahkan pola indentasi atau
  2. Tetap dengan lekukan tetapi gunakan sesuatu seperti pernyataan gema untuk mendapatkan mailx untuk menyedot email saya.

Saya terbuka untuk alternatif selain heredoc, tetapi jika ada cara untuk menyiasatinya, ini adalah sintaks pilihan saya.

Bratchley
sumber

Jawaban:

113

Anda dapat mengubah operator di sini-doc menjadi <<-. Anda kemudian dapat membuat indentasi sini-doc dan pembatas dengan tab:

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

Perhatikan bahwa Anda harus menggunakan tab , bukan spasi untuk membuat indentasi dokumen di sini. Ini berarti contoh di atas tidak akan berfungsi disalin (Stack Exchange menggantikan tab dengan spasi). Tidak ada tanda kutip di sekitar EOFpembatas pertama , jika tidak ekspansi parameter, penggantian perintah, dan ekspansi aritmatika tidak berlaku.

choroba
sumber
Keren, itu memperbaiki masalah indentasi tetapi sekarang tidak memperluas variabel yang saya coba masukkan di sana ( $dateLastChanged) jika saya melakukan hal tanda kutip + kutipan dalam contoh Anda, tetapi jika saya mengambil tanda hubung dan mengutip dan meletakkan EOI pada baris baru itu mulai berkembang lagi.
Bratchley
1
@ JoelDavis: Cukup hapus tanda kutip, pertahankan tanda hubung.
choroba
5
Terpaksa menggunakan tab sangat menjengkelkan. Apakah ada cara yang baik di sekitarnya?
con-f-use
2
@ con-f-use: Anda dapat mencoba sesuatu seperti cat << EOF | sed 's/^ *//'dan sebagainya.
choroba
4
Atau bahkan lebih baik: cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. Ini menghilangkan jumlah ruang sebelumnya di baris pertama dari setiap baris dalam dokumen di sini (terima kasih kepada anubhava ).
con-f-use
5

Jika Anda tidak memerlukan substitusi perintah dan perluasan parameter di dalam dokumen-sini Anda, Anda dapat menghindari menggunakan tab dengan menambahkan spasi utama ke pembatas:

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

Saya tidak bisa menemukan cara untuk menggunakan trik ini dan menjaga ekspansi parameter.

itsadok
sumber
1
Bagi saya, ini adalah satu-satunya jawaban yang memecahkan masalah indentasi tanpa menggunakan spasi. shell-checkakan menemukan perubahan indentasi yang tidak cocok dengan spasi dalam string yang dikutip. Gunakan tanda kutip ganda untuk ekspansi parameter?
Tom Hale
4

Coba ini:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF
robz
sumber
Anda tidak dapat memiliki garis indentasi berbeda dalam heredoc dalam kasus ini. (Ini penting jika misalnya isinya skrip.)
ivan_pozdeev
2

Hmm ... Sepertinya Anda bisa mengambil keuntungan lebih baik dari --formatargumen di sini untuk digunakan --printfsebagai gantinya dan hanya melewati banyak di atas pipa. Juga, Anda if...fiadalah perintah majemuk - itu bisa mengambil redirect yang semua perintah yang terkandung akan mewarisi, jadi mungkin Anda tidak perlu membuat sarang heredoc sama sekali.

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
sumber
Ya revisi saya sebelumnya mengatakan saya tidak keberatan bagian sed/ awk. Bagian dari revisi saya hari ini adalah untuk mengeluarkannya karena itu tidak sesuai dengan pertanyaan. Either way itu enam dari satu setengah lusin yang lain.
Bratchley
@Bratchley - sial. Kalimat terakhir itu akan mengalihkan perhatian saya untuk sisa hari itu.
mikeserv
Bagaimana maksudmu?
Bratchley
1
@Bratchley - Sepertinya teka-teki.
mikeserv
Ha. Tidak yakin dari negara mana Anda berasal tetapi itu adalah ungkapan umum di Amerika. Artinya "Pendekatan yang berbeda untuk tujuan yang sama." Solusi Anda tidak berkeliling heredoc.
Bratchley
0

Metode lain adalah 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
sumber