ネストのインデントと一致するようにヒアドキュメントをインデントできません


62

スクリプティングに「最初の世界の問題」がある場合、これがそれです。

更新するスクリプトに次のコードがあります。

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

スクリプトは問題なく電子メールを送信しますが、mailxコマンドはifステートメント内にネストされているため、2つの選択肢が残っているように見えます。

  1. EOI新しい行を入れて、インデントパターンを分割するか、
  2. インデントを維持しますが、エコーステートメントのようなものを使用して、mailxに電子メールを吸い込ませます。

私はヒアドキュメントの代替案を受け入れていますが、これを回避する方法があれば、それは私の好みの構文です。

回答:


113

here-doc演算子をに変更できます<<-。次に、here-doc と区切り文字の両方をタブでインデントできます。

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

here-docをインデントするには、スペースではなくtabsを使用する必要があることに注意してください。つまり、上記の例はコピーされません(Stack Exchangeはタブをスペースに置き換えます)。最初のEOF区切り文字を引用符で囲むことはできません。そうでないと、パラメーター展開、コマンド置換、および算術展開が有効になりません。


かっこいい、インデントの問題は修正されましたが$dateLastChanged、例でハイフンとクォートを行う場合は、そこに入れようとしている変数を展開していませんが、ハイフンとクォートを取り出してEOIを新しい行が再び展開を開始します。
ブラッチリー

1
@JoelDavis:引用符を削除するだけで、ハイフンを保持します。
チョロバ

5
タブの使用を余儀なくされるのは非常に面倒です。それを回避する良い方法はありますか?
CON-F-使用

2
@ con-f-use:のようなものを試すことができcat << EOF | sed 's/^ *//'ます。
チョロバ

4
あるいはさらに良いです:cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'。これにより、ヒアドキュメントのすべての行から最初の行の先行スペースの量が削除されます(anubhavaに感謝)。
con-f-use

5

ヒアドキュメント内でコマンドの置換やパラメーターの展開が必要ない場合は、区切り文字に先頭のスペースを追加することでタブの使用を回避できます。

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

ただし、このトリックを使用してパラメーターの拡張を維持する方法がわかりませんでした。


1
私にとって、これはスペースを使用せずにインデントの問題を解決する唯一の答えです。shell-check引用符で囲まれた文字列のスペースと一致しないインデントの変更を検出します。パラメーターの拡張に二重引用符を使用しますか?
トム・ヘイル

4

これを試して:

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

この場合、ヒアドキュメント内で異なるインデントの行を使用することはできません。(これは、たとえばコンテンツがスクリプトの場合に重要です。)
ivan_pozdeev

2

うーん... --formatここでの議論をうまく利用して、--printf代わりに使用して、パイプにたくさん渡すことができるようです。また、あなたif...fiは複合コマンドです-それは含まれているすべてのコマンドが継承するリダイレクトを取ることができるので、おそらくヒアドキュメントをネストする必要はありません。

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

ええ、私の以前の改訂版は、私はsed/のawk部分を気にしないと言っていました。今日の私の改訂の一部は、それが問題に密接な関係がないので、それを取り除くことでした。いずれにせよ、それは他の半ダースの6つです。
ブラッチリー

@Bratchley-いまいましい。その最後の文は、その日の残りの時間、私を混乱させます。
mikeserv

どういう意味ですか?
ブラッチリー

1
@Bratchley-なぞなぞのように見える。
mikeserv

ハ。出身国はわかりませんが、それはアメリカでは一般的な言い回しです。「同じ目的への異なるアプローチ」を意味します。しかし、あなたのソリューションはヒアドキュメントを回避します。
ブラッチリー

0

他の方法はヒアストリングです:

    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"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.