標準エラー出力に色を付けて標準出力と区別しやすいようにするには

結論を先に書くと、以下のようにするがいまのところよさそうである。

(foobarcmd; 2>&1 >&3 | perl -npe 'BEGIN {$|=1} s/^(.*)$/\e[31m$1\e[m/' >&2) 3>&1

foobarcmd のところに任意のコマンドを書く。

このスクリプトの組み立て方。

まず、色をつけるにはエスケープシーケンスを各行に付ければよくて、それをPerlのワンライナーでパイプ処理することにする。 Perlでなくてもなんでもいいとは思うが、Perlならどこの環境にもあると思うので。

エラー出力のみをパイプ処理するには、以下のような感じにしてみる。

(foobarcmd; 2>&1 >&3 | PERLONELINER >&2) 3>&1

コマンドのエラー出力をパイプに渡すために 2>&1 を付けて、標準出力は次のPerlワンライナーを通さないようにするために >&3 として別のファイル記述子にリダイレクトする。 2>&1>&3 の順番を入れ替えると上手く動かない。 Perlワンライナーが処理した結果は本来標準エラー出力に出したいので、>&2 としてPerlの出力をエラー出力にリダイレクトする。ここまでを括弧で囲んだ上で、ファイル記述子3にリダイレクトしていた出力を本来の標準出力に戻すために 3>&1 と書く。

次にPerlワンライナーを書くが、行頭に色を付けるエスケープシーケンスを付けて、行末にそれをリセットするエスケープシーケンスを付ければよいので、各行で s/^(.*)$/\e[31m$1\e[m/ という置換をする。従って以下のようになる。

(foobarcmd; 2>&1 >&3 | perl -npe 's/^(.*)$/\e[31m$1\e[m/' >&2) 3>&1

perlのオプションの -n は入力各行に対してワンライナーを実行するという意味。 -p は各行に対して実行した後に $_ つまり置換処理を実行した結果を表示するという意味。 -e はPerlスクリプトをその後のコマンドラインで与えるとい、ワンライナーに必須のオプション。

これでもいちおう動くが、perlが出力をバッファリングしてしまうので、それを解除するためにワンライナーの先頭に BEGIN {$|=1} と書く。

(foobarcmd; 2>&1 >&3 | perl -npe 'BEGIN {$|=1} s/^(.*)$/\e[31m$1\e[m/' >&2) 3>&1

これでできあがり。

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。