6

パイプされた出力をgrepするときに、grepがANSIカラーエスケープを尊重するようにするにはどうすればよいですか? grep の代わりに何か他のもの (perl?) を使用しても問題ありません。

私のユーザーケース: したい

 gcc foobar.c | colorgcc | grep regexp
 ls --color | grep filename

色でうまく動作します (ANSI エスケープを使用する UNIX 端末で)。

私が望む動作のテスト例:

echo -e "he\e[35mllo\e[00m" world |grep hell ==> he\e[35mllo\e[00m world 
echo -e "\e[35m removed line\nhello\e[00m" world |grep hell ==> \e[35mhello\e[00m world
echo -e "\e[35m rem\e[1moved line\nhello\e[00m" world | grep hell ==> \e35m\e1mhello\e[00m world

現在、最初の行は空の文字列を示し、2 行目は色付けされていない文字列 'hello\e[00m world' を示しています。ここで、\e[35m と \e00m は色 (属性) 修飾子です。文字の色は、形式 \e[P1; の最後のいくつかの色 (属性) エスケープ シーケンスによって決まります。P2; .. m ここで、P1、P2 などは一連の数字です。\e[P1m\e[P2m は \e[P1;P2m と同等です。\e[0m は色をデフォルトにし、以前のすべての \e[..m シーケンスを忘れます: \e[34m\e[0m は \e[0m と同等です。いくつかの独立した属性 (太さ、背景の色、前景/文字の色) があります。エスケープ シーケンス内の各数値は、そのうちの 1 つのみに影響します。したがって、 \e[1m\e[35m は \e[1;35m と同等ですが、 \e[35;1m や \e[35m ; とは異なります。ただし、\e[34m\e[35m は \e[35m と同等です。どちらも同じ属性に影響するからです (つまり、

4

1 に答える 1

2

これは非常に興味深い問題です。ここに私が思いついたものがあります。それはかなり醜いですが、仕事を成し遂げているようです:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
  grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell`

検索している用語は最後に配置されます (「地獄」の代わりに)。提供されたテキストの例をいくつか示します (hexdump を使用して色を表示します)。

$ echo -e "he\e[35mllo\e[00m" world |
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` |
> hexdump -C
00000000  1b 5b 30 6d 68 65 1b 5b  33 35 6d 6c 6c 6f 1b 5b  |.[0mhe.[35mllo.[|
00000010  30 30 6d 20 77 6f 72 6c  64 0a                    |00m world.|
0000001a

$ echo -e "\e[35m removed line\nhello\e[00m" world |
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` |
> hexdump -C
00000000  1b 5b 33 35 6d 68 65 6c  6c 6f 1b 5b 30 30 6d 20  |.[35mhello.[00m |
00000010  77 6f 72 6c 64 0a                                 |world.|
00000016

最初の sed コマンドは、現在の色設定を各行の先頭に追加します。これは、grep がスキップする行に色が設定されている 2 番目の例で必要です。grep の引数である sed コマンドは、検索語の各文字間の任意の数のカラー エスケープに一致する正規表現を挿入します。

これがegrepバージョンです:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
  egrep `sed 's/./\0(\x1b\\\\[[0-9]*m(;[0-9]*m)*)*/g' <<< hell`
于 2013-02-06T22:50:02.040 に答える