按颜色过滤命令的输出

按颜色过滤命令的输出

我正在运行一个实用程序,该实用程序不提供过滤其输出的方法。输出文本中没有任何内容表明特定函数失败,但它确实显示为红色。输出太长,以至于最后当它报告一些错误时,我无法总是滚动查看发生错误的输出。

如何过滤掉非红色文本?

伪代码:

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 解释控制字符。

相关内容