コマンド出力の前にプレフィックスを付けて戻り値を確認する最良の方法

コマンド出力の前にプレフィックスを付けて戻り値を確認する最良の方法

コマンド出力にプレフィックスを付けますが、戻り値を確認できる以下のコードより良い方法はありますか?

command > "$tmpfile" 2>&1
ret=$?
sed 's/^/  | /' "$tmpfile"
if [[ ! "$ret" -eq 0 ]]; then
    rm "$tmpfile"
    exit 1
fi

ベストアンサー1

他の一部のシェルでは、bashこのオプションを使用できますpipefail。このオプションを使用すると、パイプの終了状態は、一番右のコンポーネントの終了状態ではなく、失敗した一番右のコンポーネントの終了状態になります。

(set -o pipefail; cmd | sed 's/^/  | /') || exit

別のオプションは、パイプを使用するのではなく、stdoutをプロセス置換にリダイレクトすることです。

cmd > >(sed 's/^/  | /') || exit

この場合、バックグラウンドで開始されて待機しませんが、sed次のコマンドが実行されるまで書き込みが完了していない可能性があります。

特に、パイプラインの各コンポーネントの終了状態を記録する特別な配列(zshにはそれに対応する配列があります)がbashあります。$PIPESTATUS$pipestatus

cmd | sed 's/^/  | /'; ret=${PIPESTATUS[0]}
[ "$ret" -eq 0 ] || exit "$ret"

POSIXlyでは、次のことができます。

{
  ret=$(
    exec 4>&1
    {
      cmd 3>&- 4>&-
      echo "$?" >&4
    } | sed 's/^/  | /' >&3 3>&- 4>&-
  )
} 3>&1
[ "$ret" -eq 0 ] || exit "$ret"

ヘルパー機能を使用できます。

prefix() (
  prefix=$1; shift
  exit "$(
    exec 4>&1
    { 
      "$@" 3>&- 4>&-
      echo "$?" >&4 3>&- 4>&-
    } | PREFIX=$prefix awk '{print ENVIRON["PREFIX"] $0}' >&3 3>&- 4>&-
  )"
) 3>&1

prefix '  | ' cmd

awk(任意のプレフィックスを使用できるように切り替えられます。

おすすめ記事