stdoutとstderrをファイルに保存し、出力を再生成します。

stdoutとstderrをファイルに保存し、出力を再生成します。

出力を次のファイルにリダイレクトしました。

$ ./test.bash 2> >(sed 's/^/stderr: /' >> output) > >(sed 's/^/stdout: /' >> output)
$ cat output
  stdout: Hello World!
  stderr: error

元のコマンドの出力を正確に再現したいと思います./test.bash。私が試したことは次のとおりです。

$ cat output | tee >(grep '^stdout: '|sed 's/^stdout: //') >(grep '^stderr: '|sed 's/^stderr: //' 1>&2) >/dev/null 2>&1 | cat
  error
  Hello World!

明らかに、私は出力が正しい順序で行われることを望みます。これを行う最良の方法は何ですか?

答え1

現在の文書によっては、次のことが可能です。

awk '
    /^stdout:/ { print substr($0, 9) } 
    /^stderr:/ { print substr($0, 9) > "/dev/stderr" }
    ' output

「録音スクリプト」を少し変更すると、よりエレガントになることがあります。

答え2

あなたtest.bashが次のように見える場合:

echo "Hello World!"; echo error >&2

このスクリプトは次loop.shのとおりです。

./test.bash &> original ; echo original: ; cat original;     ok=0 ; er=0
for i in {1..100}; do
   rm output ; printf "(ok%d:er%d) running again: " $ok $er
   ./test.bash 2> >(cat >>output) > >(cat >>output)  #<-EXAMINED COMMAND
   if diff output original >/dev/null;
      then printf "result equal...."; ((ok++))
      else printf "result DIFFERENT"; ((er++)); fi
done

出力ファイルが常に順番に保持されることを証明する必要があります。間違った(私のテストでは約37%)

問題は、並列プロセス、制御されていないリダイレクトバッファリング、および実行速度を妨げることです。

「expect」パッケージの「unbuffer」ツールソリューションを使用します(インストールできる場合)。使用:

(sleep 0.01 ; unbuffer ./test.bash)

上記のスクリプトの4行目の./test.bashの代わりに完全に実行されます(エラー0%)。

答え3

すべての入力行がまたはで始まる場合は、次のことがstderr:できstdout:ます。

perl -ne 's/^std(...):\s*//; $1 eq "err" ? print STDERR : print' output

または、最新バージョンのbashを使用してください。

while read -r out line; do
    [[ $out =~ ^stderr ]] && echo "$line" >&2 || echo "$line"
done < output 

関連情報