如何语法突出显示 bash 输出(一些帮助信息)?

Posted

技术标签:

【中文标题】如何语法突出显示 bash 输出(一些帮助信息)?【英文标题】:How to syntax highlight a bash output (some help information)? 【发布时间】:2016-12-20 05:50:54 【问题描述】:

我经常通过命令的--help 标志获得一些帮助信息,该标志在终端上提供如下输出:

$ vmtkimagereader --help

Creating vmtkImageReader instance.
Automatic piping vmtkimagereader
Parsing options vmtkimagereader

vmtkimagereader : read an image and stores it in a vtkImageData object
  Input arguments:
   -id Id (str,1); default=0: script id
   -handle Self (self,1): handle to self
   -disabled Disabled (bool,1); default=0: disable execution and
     piping

我想像upper half of the link 那样语法高亮输出(对不起,我只能发布 1 个链接)。我试过突出显示和 pygmentize。但是,highlight 需要指定语法,并且 pygmentize 将输出呈现为错误的样式(在链接的下半部分)。

我想知道是否有一种方法可以使语法突出显示like this。我需要为 pygmentize 指定样式吗?还是我必须求助于其他解决方案?

谢谢!

【问题讨论】:

似乎 css 将段落渲染得相当好......但是如何在终端中做到这一点? 您有 2 个选项(都非常简单),您可以使用 ANSI 转义序列为文本着色,也可以使用 tput 完成相同的操作。这假定您知道您希望文本的每个部分是什么颜色,以便您可以在适当的时间设置颜色并在完成后重置为普通文本。例如见Ansi Color Sequences 谢谢@DavidC.Rankin。 ANSI 转义真的很棒。 【参考方案1】:

ANSI 转义字符串

使用 ANSI 转义序列来实现您想要的,您可以创建一个格式字符串(由前缀 \e[ 和附加 m 表示),其中 38;5;0..255 是文本的 256 色(0..255 是可用颜色代码的范围),48;5;0..255 是 256 色背景。例如,

echo -e "\e[38;5;0;48;5;255mText\e[0m"

将打印带有白色背景(颜色代码255)的黑色文本(颜色代码0)。注意echo 命令它需要扩展模式(由-e 标志切换)来解释ANSI 转义字符串。

注意尾随\e[0m 取消设置颜色,否则在此命令之后打印的所有带有echo 的文本都将保留格式。 \e[0m 重置它。

注意一个有趣的用例,它也会导致错误。在结尾 \e[0m 之前放置一个感叹号会导致以下输出:

nick@nick-lt:~$ echo -e "\e[38;5;0;48;5;255mText!\e[0m"
bash: !\e[0m: event not found

这是因为! 是 Bash 字符串扩展的一部分。请参阅有关此 SO 问题here 的更多信息。为了使这项工作按预期工作,我们需要做:

echo -e "\e[38;5;0;48;5;255mText"'!'"\e[0m"

因为单引号不会被扩展。


如何使用 ANSI 转义序列打印每种可用的颜色。

将这些保存在一个名为color-functions.sh的文件中:

function color_list_text() 
    # First paramter can be an optional background color
    local BGCOLOR="$1"

    COLOR=
    # Loop through the number range 0 to 255
    for COLOR in 0..255; do
        local BGCOLORFORM=""
        # If our first parameter has a value, then create a background
        # format in ANSI escape sequence, assign to $BGCOLORFORM
        [[ -z "$BGCOLOR" ]] && BGCOLORFORM="48;5;$BGCOLOR;"

        # Create the whole ANSI escape sequence, assign to $TEXTFORM
        local TEXTFORM="$BGCOLORFORM38;5;$COLORm"

        echo -en "\e[$TEXTFORM $COLOR\t\e[0m"

        [[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
    done

    return 0


function color_list_text_backgrounds() 
    local TEXTCOLOR="$1"

    local COLOR
    for COLOR in 0..255; do
        local TEXTCOLORFORM=""
        [[ -z "$TEXTCOLOR" ]] && TEXTCOLORFORM="38;5;$TEXTCOLOR;"

        local TEXTFORM="$TEXTCOLORFORM48;5;$COLORm"

        echo -en "\e[$TEXTFORM $COLOR\t\e[0m"

        [[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
    done

    return 0

然后,在另一个文件中,在 source'd 之后调用函数:

source color-functions.sh

# Loops through and prints all ANSI escape sequence's available text colors
color_list_text
# Loops through and prints all ANSI escape sequence's available text backgrounds
color_list_backgrounds

这是一个兼具两者的功能......但我认为它有点矫枉过正,因为输出太大(将输出 256 * 256 = 2^16 个组合):

function color_list_text_and_backgrounds() 
    local BG
    for BG in 0..255; do
        local TEXT
        for TEXT in 0..255; do
            echo -en "\e[38;5;$TEXT;48;5;$BGm $TEXT\t\e[0m"

            if [[ $(( (TEXT + 1) % 8 )) -eq 0 ]]; then
                if [[ $(( ((TEXT + 1) / 8) )) -eq 16 ]]; then
                    local INVBG=$(( (BG + 128) % 256 ))
                    echo -en "\e[38;5;$INVBG;48;5;$BGm $BG\t\e[0m"
                else
                    echo -en "\e[48;5;$BGm\t\e[0m"
                fi

                echo
            fi
        done
    done

    return 0


您的用例

要为某些事物着色某些颜色,我们可以使用egrep -i-i 标志不区分大小写)和GREP_COLOR 变量:

echo "Some string to color" | \
    GREP_COLOR='38;5;200' egrep -i --color=always 'some' | \
    GREP_COLOR='38;5;100' egrep -i --color=always 'string|color'

或者我们可以真正聪明地实现这个功能:

color_text_match() 
    MATCHSTRING="$1"
    COLOR="$2"

    [[ -z "$MATCHSTRING" ]] && echo "color_text_match: No color specifies." 
    [[ -z "$COLOR" ]] && COLOR="214"   # Default orange

    GREP_COLOR="38;5;$COLOR" egrep -i --color=always "$MATCHSTRING"

然后:

echo "Some string to color" | \
    color_text_match "Some" | \
    color_text_match "string" | \
    color_text_match "to" "226"

【讨论】:

【参考方案2】:

谢谢你,@NickBull。你对 ANSI 转义的介绍对于像我这样的新手来说是一个很好的教程 :-) 我已经尝试了你所有的代码并让我的 color_help.sh 来呈现输出:

function color_help() 
    COLOR_NUM="5"
    COLOR_CAP_WORD="4"
    COLOR_KEY_WORD="2"

    GREP_COLOR="38;5;$COLOR_NUM" egrep -E --color=always "\b[0-9]+(\.[0-9]+)*\b|$" | \
    GREP_COLOR="38;5;$COLOR_CAP_WORD" egrep -E --color=always "\b([A-Z][a-z]+)+\b|$" | \
    GREP_COLOR="38;5;$COLOR_KEY_WORD" egrep -E --color=always "\b(and|bool|default|float|for|from|int|self|str)\b|$"

【讨论】:

以上是关于如何语法突出显示 bash 输出(一些帮助信息)?的主要内容,如果未能解决你的问题,请参考以下文章

ccat – 使用语法突出显示输出内容

vim 在 Docker 容器中使用时不突出显示语法

如何在 Visual Studio Code 中自动设置语法突出显示的语言

在 CMake 项目中为 Qt 关键字启用语法突出显示

ccat – 使用语法突出显示输出内容

如何在交互式调试期间突出显示和着色 gdb 输出?