【问题标题】:grep through colored text , e.g. gcc | colorgcc | grep regexpgrep 通过彩色文本,例如海合会 |颜色gcc | grep 正则表达式
【发布时间】:2013-01-22 06:03:13
【问题描述】:

grep 管道输出时如何使 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世界'。这里 \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。有几个独立的属性(粗体、背景颜色、前景/字母颜色);转义序列中的每个数字只影响其中一个。因此 \e[1m\e[35m 等价于 \e[1;35m 但不是 \e[35;1m 也不 \e[35m ;但是,\e[34m\e[35m 等价于 \e[35m,因为它们都影响相同的属性(即,字母/前景的颜色)。

【问题讨论】:

  • 第一次尝试解决方案:gcc foobar.c | colorgcc | less -R +/regexpless -R 了解颜色代码并会在它们周围搜索。

标签: regex perl grep


【解决方案1】:

这是一个非常有趣的问题,这就是我想出的。它非常丑陋,但似乎完成了工作:

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`

【讨论】:

  • 谢谢!这不能正常工作: echo -e "\e[35m removed\e[0m line\nh\e[34mel\e[32mlo\e[00m"
  • 哦,对不起!不,这很好用。但它是否适用于任意正则表达式?如果我用“egrep”替换最后一个“grep”,它似乎不起作用
  • 如果将 grep 替换为 egrep,则可以删除第二个 sed 命令中紧接在 () 之前的所有反斜杠。在编辑中添加了这个。
  • 请注意,如果您的搜索词是任意正则表达式,这将不起作用,因为插入颜色转义可能会改变原始正则表达式的行为。
  • 谢谢!这确实会处理重叠序列: echo -e "\e[35m rem\e[1moved line\nhello\e[00m" world 。不过,确实很酷!我不知道 sed 的 'h' 和 'H' 命令。
猜你喜欢
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多