たかまるの雑記

たまに更新

シェルでコマンドの標準出力と標準エラー出力を別の変数に入れる

コマンドの標準出力と標準エラー出力を別々の変数に格納する

サンプルのコマンド
function command {
  echo "[-- stdout --]"
  echo "[-- stderr --]" >&2
  return 3
}


1. 標準エラー出力をファイルに書く

ファイルに書いてあとから読む方法は、
わかりやすいし、コマンドの戻り値もとれる

tmpfile=$(mktemp --tmpdir=.)
stdout=$(command 2>$tmpfile)
echo $?
stderr=$(cat $tmpfile)
rm $tmpfile
echo stdout=$stdout stderr=$stderr
結果
3
stdout=[-- stdout --] stderr=[-- stderr --]

でも、ファイルをつくりたくない。


2. eval、コマンド置換、プロセス置換を使う

こんな感じにコマンド置換やプロセス置換をしてevalに渡す

stdout= stderr=

eval "$((command) 2> >(stderr=$(cat);typeset -p stderr) > >(stdout=$(cat);typeset -p stdout))"

echo $?
echo stdout=$stdout stderr=$stderr
結果
0
stdout=[-- stdout --] stderr=[-- stderr --]

evaldeclare -- stdout="xxdeclare -- stderr="xx"が実行されることで変数に設定される
typeset -p namedeclare -- name=value"を出力する

戻り値はとれない。 別の変数に設定すればとれる。

stdout= stderr=

eval "$((command) 2> >(stderr=$(cat);typeset -p stderr) > >(stdout=$(cat);typeset -p stdout);ret=$?;typeset -p ret)"

echo stdout=$stdout stderr=$stderr ret=$ret
結果
stdout=[-- stdout --] stderr=[-- stderr --] ret=3

戻り値が別の変数になってしまうのが残念。


3. kshを使う

kshだとシンプルにできる

stdout= stderr=

stderr=${ { stdout=$(command); } 2>&1; }

echo $?
echo stdout=$stdout stderr=$stderr
結果
3
stdout=[-- stdout --] stderr=[-- stderr --]

戻り値もとれるし、良い。