標準エラー出力にだけ色を付ける

  • 5
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

概念としては別のものですが、標準出力と標準エラー出力は通常同じ端末の画面に出ます。

「標準エラー出力、色分けくらいしてくれれば便利なのに」と思っていましたが、以下のように プロセス置換 (Process Substitution) を使うことで一行に収めることができます。

まず標準入力に色を付けて標準出力に流すスクリプトを用意します。書かずとも既にあるという場合はそれを使っても :ok: です。

colorize
#!/usr/bin/perl

use strict;
use warnings;

use Term::ANSIColor qw(colored);

my $color = shift || "red";

while (<>) {
    print colored($_, $color);
}

標準出力と標準エラー出力の両方にデータを流すプログラムを想定します。ここでは簡単のため、丸括弧でサブシェルを作り、中で両方の出力を行うワンライナーとしましょう。

$ ( echo foo ; echo bar >&2 )
foo
bar

foo が標準出力、bar が標準エラー出力です。この段階ではどちらも見分けがつきません。

標準エラー出力だけを先ほど用意した colorize に流したいのですが、標準出力の場所を変えずに標準エラー出力だけをこちらに流すための方法の一つとしてプロセス置換の方法があります。仕組み的には名前付きパイプと同等です。

$ ( echo foo ; echo bar >&2 ) 2> >(colorize >&2)
foo
bar
  • 標準エラー出力のリダイレクト記号 2> で、左側の標準エラー出力を右側の「ファイル」出力へリダイレクトするよう変更
  • 右側の「ファイル」は通常のファイルではなく >(...) 構文になっている。これは丸括弧内のプロセスに対する名前付きパイプとなっており、結果的に colorize の標準入力となる。
  • colorize で赤く色付けをして >&2 で標準エラー出力へ戻す。

もともと標準出力と標準エラー出力で出力バッファリングの効き方が異なるので、この「標準エラー出力色付けフィルタ」があると、当初と出力の順序やタイミングが微妙に異なってくることがあります。

記号をたくさん書くのは大変なので、工夫するとすればシェル関数にまとめたりすることでしょうか。

function colorize-stderr {
    "$@" 2> >(colorize >&2)
}
$ cat errok.sh
#!/bin/bash
echo foo
echo bar >&2
$ colorize-stderr ./errok.sh
foo
bar

参考: