我正在运行一个实用程序,该实用程序不提供过滤其输出的方法。输出文本中没有任何内容表明特定函数失败,但它确实显示为红色。输出太长,以至于最后当它报告一些错误时,我无法总是滚动查看发生错误的输出。
如何过滤掉非红色文本?
伪代码:
dolongtask | grep -color red
编辑
该命令还输出其他颜色,我需要能够过滤出去所有文字不是红色的。文本着色也是多行的。
答案1
切换颜色是通过转义序列嵌入到文本中。总是程序问题ANSI 转义序列,因为现在几乎所有终端都支持这一点。
将前景色切换为红色的转义序列是\e[31m
,其中\e
指定转义字符(八进制 033、十六进制 1b,也称为 ESC,^[
以及各种其他名称)。 30-39 范围内的数字设置前景色;其他数字设置不同的属性。\e[0m
将所有属性重置为其默认值。运行cat -v
以检查程序打印的内容,它可能会使用一些变体,例如\e[0;31m
首先重置所有属性,或者\e[3;31
同时打开斜体(许多终端不支持)。
在 ksh、bash 或 zsh 中,您可以使用$'…'
在引号内启用反斜杠转义,这样您可以通过键入$'\e'
来获取转义字符。请注意,您必须将要传递给的任何反斜杠加倍grep
。在 中/bin/sh
,您可以使用"$(printf \\e)"
或键入文字转义字符。
使用 GNUgrep -o
选项,以下代码片段会过滤红色文本,假设它以转义序列 开头\e[31m
,以\e[0m
或\e[30m
在同一行结束,并且不包含嵌入的转义序列。
grep -Eo $'\e\\[31m[^\e]*\e\\[[03]?m'
以下awk
代码片段提取红色文本,即使它是多行的。
awk -v RS='\033' '
match($0, /^\[[0-9;]*m/) {
color = ";" substr($0, 2, RLENGTH-2) ";";
$0 = substr($0, RLENGTH+1);
gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
red = (color ~ /1;*$/)
}
red'
这是保留颜色更改命令的变体,如果您要过滤多种颜色(此处为红色和洋红色),这可能会很有用。
awk -v RS='\033' '
match($0, /^\[[0-9;]*m/) {
color = ";" substr($0, 2, RLENGTH-2) ";";
printf "\033%s", substr($0, 1, RLENGTH);
$0 = substr($0, RLENGTH+1);
gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
desired = (color ~ /[15];*$/)
}
desired'
答案2
您可以使用 grep 查找控制字符,其中一些控制字符负责在终端上显示漂亮的颜色。
dolongtask | grep '[[:cntrl:]]'
例如,这会将红色“test”回显到 grep 中,grep 会因为它被控制字符包围而找到它:
$ echo -e '\033[00;31mtest\033[00m' | grep --color=none '[[:cntrl:]]'
test <-- in red
只是--color=none
为了确保 grep 不会将自己的着色应用于匹配的输出,而是忠实地打印整行,以便 shell 解释控制字符。