カラー出力を印刷するターミナル(ls
やgcc
など)からコマンドを実行すると、カラー出力が印刷されます。私の理解から、プロセスは実際には ANSIエスケープコード を出力しており、端末は色をフォーマットします。
ただし、同じコマンドを別のプロセス(カスタムCアプリケーションなど)で実行し、出力をアプリケーション自体の出力にリダイレクトすると、これらの色が保持されません。
プログラムは、テキストをカラー形式で出力するかどうかをどのように決定しますか?環境変数はありますか?
環境変数はありますか?
はい。これはTERM
環境変数です。これは、決定プロセスの一部として使用されるものがいくつかあるためです。
すべてのプログラムが単一の決定フローチャートに同意するわけではないため、ここで一般化することは困難です。実際、M。キットの回答で述べたGNU grep
は、予期しない結果を伴うやや珍しい決定プロセスを使用する外れ値の良い例です。したがって、非常に一般的な用語では、次のようになります。
isatty()
によって決定される端末デバイスでなければなりません。TERM
環境変数が存在し、その値がデータベースレコードと一致している必要があります。TERMCAP
環境変数を使用してtermcapデータベースの場所を指定できます。そのため、一部の実装では、second環境変数があります。max_colors
_フィールドがあります。実際にはカラー機能を持たない端末タイプには設定されません。実際、すべての色付け可能な端末タイプについて、色の機能がないことを示す名前に_-m
_または_-mono
_が追加された別のレコードがあるというterminfo規則があります。set_a_foreground
_および_set_a_background
_フィールドがあります。単にisatty()
をチェックするよりも少し複雑です。 さらにいくつかのことで複雑にされます:
isatty()
チェックをオーバーライドするコマンドラインオプションまたは構成フラグを追加し、プログラムalwaysまたはneverは、出力として(着色可能な)端末があると想定します。たとえば:ls
には_--color
_コマンドラインオプションがあります。ls
は、CLICOLOR
(不在の意味never)と_CLICOLOR_FORCE
_(その存在の意味)を常に調べます)環境変数、および_-G
_コマンドラインオプションも使用できます。TERM
の値に対する応答をハードワイヤードしています。すでに述べたように、GNU grep
は、実際にはこれらの追加の複雑さの一部を示します。termcap/ terminfoを調べず、制御シーケンスを発行するように配線し、TERM
環境変数に応答を配線します。
Linux/Unixポートにはこのコードがあります 。これは、TERM
環境変数が存在し、その値がハードワイヤード名dumb
と一致しない場合にのみ色付けを有効にします。
int should_colorize(void) { char const * t = getenv( "TERM"); return t && strcmp(t、 "dumb")! = 0; }
したがって、TERM
が_xterm-mono
_である場合でも、GNU grep
は、vim
などの他のプログラムが色を放出しないことを決定します。
Win32ポートにはこのコードがあります 。これは、TERM
環境変数が存在しない場合または存在する場合に色付けを有効にします。そしてその値は、ハードワイヤード名dumb
と一致しません:
int should_colorize(void) { char const * t = getenv( "TERM"); return! (t && strcmp(t、 "dumb")== 0); }
grep
の色に関する問題GNU grep
の色分けは実際に悪名高いです。それは実際には端末出力を構築する適切な仕事をしませんが、むしろいくつかのハードワイヤード制御シーケンスでその出力のさまざまなポイントで非難するだけでそれが十分であると期待して、それは実際に特定の状況で誤った出力を表示します。
これらの状況では、端末の右端にあるものを色分けする必要があります。端末出力を適切に行うプログラムは、自動右マージンを考慮する必要があります。 これに加えて端末がそれらを持たない可能性があります(terminfoの_auto_right_margin
_フィールドを参照)。自動右マージンは、多くの場合、DEC VTの前例の保留行の折り返しに従います。 GNU grep
はこれを考慮しておらず、即時の行の折り返しを期待していないため、色付きの出力が正しくありません。
カラー出力は簡単なものではありません。
grep --color
_は正しい出力を表示しません "。 xterm FAQ。見えない島。expectパッケージのunbuffer
コマンドは、最初のプログラムからの出力と2番目のプログラムへの入力を分離します。
次のように使用します。
unbuffer myshellscript.sh | grep value
私はいつもansibleと自家製の ctee スクリプトでそれを使用しているので、ログファイルを通常の(色付けされていない)出力のままにしながら、ターミナルでカラー出力を確認できます。
unbuffer ansible-playbook myplaybook.yml | ctee /var/log/ansible/run-$( date "+%F" ).log