trコマンドはgrepからパイプされたカラー出力を処理できません。

trコマンドはgrepからパイプされたカラー出力を処理できません。

私はmacOS 12.3.1を実行しています。

.zshrcにいくつかの行を追加しました。

export GREP_OPTIONS='--color=always'
export GREP_COLOR='1;35;40'

後でgrep出力をtrにパイプすると、同じ数の行が返されますが、すべての行は空です。

たとえば、

grep ^.....$ /usr/share/dict/words | tr "[:lower:]" "[:upper:]"

10230 個の空行を返します。

これが期待されるか。

答え1

カラーマッチングを出力するには、grepマッチングの前後にカラーエスケープシーケンスを作成します。

これは、端末に背景色および/または前景色を変更するように指示する指示です。

それを実現することが重要ですはいテキストとともに出力に表示されます。端末はこれをグラフィック記号で表示せず、特別な指示として理解しているため、これは表示されません。

エスケープシーケンスはESC文字(0x1bバイト(8進数で033)、ASCIIとも呼ばれる、\eまたは^[)で始まり、その後に制御文字である必要がないいくつかの文字が続きます。

出力を次にパイプしてこれらの文字を表示できます。

$ echo + | grep --color=always . | sed -n l
\033[01;31m\033[K+\033[m\033[K$
$ echo + | grep --color=always . | od -An -vtc -tx1 -to1
 033   [   0   1   ;   3   1   m 033   [   K   + 033   [   m 033
  1b  5b  30  31  3b  33  31  6d  1b  5b  4b  2b  1b  5b  6d  1b
 033 133 060 061 073 063 061 155 033 133 113 053 033 133 155 033
   [   K  \n
  5b  4b  0a
 133 113 012

(ここには個々のバイトの16進数と8進数の値も含まれます)

または(非標準で不明ですが):

$ echo + | grep --color=always . | cat -A
^[[01;31m^[[K+^[[m^[[K$

出力で事前一致と事後一致があるgrepことを確認できます。\e[01;31\e[K\e[m\e[K

与えられた端末が認識するエスケープシーケンスと端末によってどのように異なるか。たとえば、xtermの場合は、次を参照してください。そこの仕様。上記の内容は最近かなり一般的です。

\e[- で始まり終わる数字の場合、m端末は;- で区切られた各数字を、今後作成されるテキストに適用する別のレンダリング属性として理解します。たとえば、太字で1表示するには、31前景色を赤に設定します。

\e[Kカーソルから行末まで画面を消去するように端末に指示するエスケープシーケンスです。

したがって、端末は実際に次のことを確認します。

<bold-fg_red><clear-to-eol>+<reset-all-attributes><clear-to-eol>

しかし、あなたがtr見るのは、ESC、[... m、および音訳を必要とする他のコンテンツだけです。

特にここでは音訳されmM色属性を変更するエスケープシーケンスがすべて異なるものに変わります。

端末文書(例:https://www.invisible-island.net/xterm/ctlseqs/ctlseqs.html上記のxterm)は、時々見つけるのが難しいか、存在しない場合は、いくつかの一般的な操作terminfoについて端末で認識されるいくつかのエスケープシーケンスを記録するデータベースを見ることができます。

次のコマンドを使用して、端末のデータベース($TERM環境変数で識別される)を手動で照会できますinfocmp

$ infocmp -xL1 | grep M,
        delete_line=\E[M,
        key_enter=\EOM,
        key_mouse=\E[M,
        parm_delete_line=\E[%p1%dM,
        scroll_reverse=\EM,

これらのタスクの詳細(能力terminfo(5))、マニュアルページ()を見ることができますman 5 terminfo

\e[Mdelete_line)は行を削除し、\e[<decimal>Mparm_delete_line<decimal>は行を削除します。したがって、大文字で音訳すると、シェーディングシーケンスは行削除シーケンスになります。

通常、カラー出力は端末用にのみ使用されるため、後処理は必要ありません。これは、色付けをサポートするほとんどのコマンドが出力が端末に到達しないときに無効にする理由です。

GNUの場合、grepすでに見つけたように、その動作を取得するには--color=auto(または)が必要です。grep --color

色を続けるには、パイプラインの最後のコマンド、つまり端末に出力されるコマンドに色を移動する必要があります。

<file tr '[:lower:]' '[:upper:]' | grep  -xE --colour=auto '.{5}'

--colour=autoコマンドを含むスクリプトが出力をリダイレクト/後処理する場合は、カラーリングが無効になるようにここで使用されます。

ここで、正規表現は行全体(上記のオプション、メソッドで and like を-x使用する必要はありません)と一致するため、前に前景色を赤に切り替えてからプロパティを消去することもできます。^$

if [ -t 1 ]; then
  tput setaf 1 # set ANSI foreground colour
  tput bold
fi
grep...
if [ -t 1 ]; then
  tput sgr0 # turn off all attributes
fi

これは端末の正しいシーケンスをtput照会するために使用されますが、ほとんどの端末はこれを実行するので、次のようにしてシーケンスをハードコードします。terminfogrep

[ -t 1 ] && printf '\33[1;31m'
grep...
[ -t 1 ] && printf '\e[m'

[ -t 1 ]stdout(ファイル記述子1)が端末であることを確認するために使用されます。

答え2

GREP_OPTIONSに変更して --color=always解決しました。--color=auto

trと色分けされたテキストがうまくいかないと思います。

関連情報