コードブロックのインデントと一致するようにheredocをインデントすることはできません。

コードブロックのインデントと一致するようにheredocをインデントすることはできません。

スクリプトに「第1世界問題」があったら、まさにこれでした。

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

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. インデントを維持しますが、echoステートメントのようなものを使用してmailxが自分の電子メールを吸収できるようにします。

私はheredocの代替案を開いていますが、この問題を解決する方法がある場合は、これが私が好む構文です。

答え1

here-doc演算子をに変更できます<<-。その後、ここから文書をインデントできます。と区切り記号タブ付き:

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

気づくタグを使用する必要があります。、スペースの代わりに文書をインデントして区切ります。これは上記の例が再現されないことを意味します(Stack Exchangeはタブをスペースに置き換えます)。最初の区切り文字の周りに引用符を追加すると、パラメータEOF拡張、コマンド置換、および算術拡張は適用されません。

答え2

この資料でコマンドの置き換えとパラメータの拡張が不要な場合は、区切り文字に先行スペースを追加してタブの使用を回避できます。

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

ただし、このトリックを使用してパラメータを拡張したままにする方法はありません。

答え3

この試み:

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

答え4

この回答はGNU-Bash専用です。

秘密は、<<<Bashが提供する単一の単語here-docを使用して複数行のエントリにすることです。

catまた、UUoCも防止します。入力を次に提供するプロセスは必要ありませんsed

$ sed '1d;s/^    //' <<<"
    {
       TERM=$TERM
    }
    bye"

出力には、先行スペースの4つのインデントが削除され、拡張されたものとして表示$TERMされます。

{
   TERM=xterm-256color
}
bye

1dのコマンドは、引用符付きsedテキストが開いている引用符の後に改行文字で始まるため、最初に空の行を削除することです。

もちろん、実際のスクリプトでは次のようになります。破るエド——許してください。石よりseded - ループまたは条件ステートメント内にインデントするコマンドに中括弧を並べ替えます。

各データ行を区切り文字で開始すると、単純なsed置換によって可変インデント量が削除され、ブロックがインデントレベル間で自由に移動できます。

while command ; do
    if condition ; then
        variable=$(sed '1d;s/^.*|//' <<<"
                  |{
                  |   TERM=$TERM
                  |}
                  |bye
                  ")
    fi
done

最後のアイデアの1つは、一種のマクロとして機能する変数にインデント魔法を置くことです。

# put in some common definitions library section
indent='sed 1d;s/^.*|//'

# ...

while command ; do
    if condition ; then
        variable=$($indent <<<"
                  |{
                  |   TERM=$TERM
                  |}
                  |bye
                  ")
    fi
done

私たちは良い昔ながらの関数を書くことでそれを改善することができます:

# put in some common definitions library section
ind()
{
   sed '1d;s/^.*|//' <<<$1
}

# ...

while command ; do
    if condition ; then
        variable=$(ind "
                  |{
                  |   TERM=$TERM
                  |}
                  |bye
                  ")
    fi
done

その後、完全に抽象化します<<<

関連情報