grep通过彩色文本,例如gcc | colorgcc | grep regexp

时间:2013-02-06 21:35:41

标签: regex perl grep

在grepping管道输出时,如何使grep尊重ANSI颜色转义? 我很乐意使用别的东西(perl?)而不是grep。

我的用户名:我想要

 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

目前第一行给出空字符串,第二行给出未着色字符串 '你好\ e [00m world'。这里\ [35m和\ e00m是颜色(属性)修饰符:字母的颜色由形式\ e [P1;的最后几个颜色(属性)转义序列决定。 P2; ..其中P1,P2等是数字序列; \ e [P1m \ e [P2m相当于\ e [P1; P2m。 \ e [0m使颜色默认并忘记所有先前的\ e [... m序列:\ e [34m \ e [0m相当于\ e [0m。有几个独立的属性(粗体,背景的颜色,前景/字母的颜色);转义序列中的每个数字只影响其中一个。因此\ e [1m \ e [35m相当于\ e [1; 35m但不是\ [35; 1m也不是\ [35m;然而,\ [34m \ e [35m相当于\ [[35m因为它们都影响相同的attirbute(即字母/ foregrnound的颜色))。

1 个答案:

答案 0 :(得分: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将跳过的行上。作为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`