如何语法高亮显示 bash 输出(一些帮助信息)?
How to syntax highlight a bash output (some help information)?
我经常通过命令的 --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 这样的语法高亮显示输出(抱歉,我只能 post 1 link)。我试过突出显示和 pygmentize。但是,highlight 需要指定语法,而 pygmentize 将输出呈现为错误的样式(在 link 的下半部分)。
想知道有没有办法让语法高亮like this。我需要为 pygmentize 指定样式吗?还是我必须转向其他解决方案?
谢谢!
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=""
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="${BGCOLORFORM}38;5;${COLOR}m"
echo -en "\e[${TEXTFORM} ${COLOR}\t\e[0m"
[[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
done
return 0
}
function color_list_text_backgrounds() {
local TEXTCOLOR=""
local COLOR
for COLOR in {0..255}; do
local TEXTCOLORFORM=""
[[ -z "$TEXTCOLOR" ]] && TEXTCOLORFORM="38;5;${TEXTCOLOR};"
local TEXTFORM="${TEXTCOLORFORM}48;5;${COLOR}m"
echo -en "\e[${TEXTFORM} ${COLOR}\t\e[0m"
[[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
done
return 0
}
然后,在另一个文件中,在 source
之后调用这些函数:
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;${BG}m ${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;${BG}m ${BG}\t\e[0m"
else
echo -en "\e[48;5;${BG}m\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=""
COLOR=""
[[ -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"
谢谢你,@NickBull。你对 ANSI escape 的介绍对于像我这样的新手来说是一个很好的教程 :-) 我已经尝试了你所有的代码并使我的 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|$"
}
我经常通过命令的 --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 这样的语法高亮显示输出(抱歉,我只能 post 1 link)。我试过突出显示和 pygmentize。但是,highlight 需要指定语法,而 pygmentize 将输出呈现为错误的样式(在 link 的下半部分)。
想知道有没有办法让语法高亮like this。我需要为 pygmentize 指定样式吗?还是我必须转向其他解决方案?
谢谢!
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=""
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="${BGCOLORFORM}38;5;${COLOR}m"
echo -en "\e[${TEXTFORM} ${COLOR}\t\e[0m"
[[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
done
return 0
}
function color_list_text_backgrounds() {
local TEXTCOLOR=""
local COLOR
for COLOR in {0..255}; do
local TEXTCOLORFORM=""
[[ -z "$TEXTCOLOR" ]] && TEXTCOLORFORM="38;5;${TEXTCOLOR};"
local TEXTFORM="${TEXTCOLORFORM}48;5;${COLOR}m"
echo -en "\e[${TEXTFORM} ${COLOR}\t\e[0m"
[[ $(( (COLOR + 1) % 16 )) -eq 0 ]] && echo
done
return 0
}
然后,在另一个文件中,在 source
之后调用这些函数:
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;${BG}m ${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;${BG}m ${BG}\t\e[0m"
else
echo -en "\e[48;5;${BG}m\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=""
COLOR=""
[[ -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"
谢谢你,@NickBull。你对 ANSI escape 的介绍对于像我这样的新手来说是一个很好的教程 :-) 我已经尝试了你所有的代码并使我的 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|$"
}