bash:在写入标准输出之前捕获并着色部分输出
bash: Capture and colorize parts of output before writing to stdout
我正在捕获变量中 command/script 的输出。输出本质上是一个文本块。在这个问题的上下文中,让我们考虑一下:
output='In java, both Errors and Exceptions are the subclasses of some/long/path/to/file.java class. Error refers to an illegal operation at line=23 and executed by app=client
问题: 我喜欢在写入 stdout 之前对部分消息进行着色。我设法找到了一种方法,但有意义/仅适用于一个替代。
color_end=$'[0m'
color_red=$'[31m'
echo "${output//line=/${color_red}LINE=$color_end}"
我也喜欢匹配和着色其他部分(比如 <filename>.java
、app=
)。我尝试在上面的变量替换中使用正则表达式,但是 none 这些工作。出现语法错误或类似错误。
echo "${output//(line=|app=)/${color_red}$color_end}"
尝试使用 sed
,但 1) 颜色会被解释,因此在写入标准输出时 2) 正则表达式模式有点毛茸茸。
实现此目标的最佳方法是什么?
FWIW,所有匹配的部分只有一种颜色。不同的匹配部分没有不同的颜色。
我会这样做:
# Only set colors if printing to a terminal
test -t 1 && t_red1=$'3[31m' t_01=$'3[0m'
# List here the regexes to highlight
echo "$output" |
sed -E 's/[[:alnum:]_]+=|[^[:space:]]+\.java'/"$t_red1&$t_01/g"
- 这可以使用
BASH_REMATCH
在纯 bash 中完成,但 sed
更简单,而且可能更有效。
- 文件路径的正则表达式在这里有效,但很脆弱 - 路径中的 space 会破坏它。
- 但您可以使用此模板添加要突出显示的正则表达式。
test -t 1
确保仅当 stdout (fd 1) 是终端时才设置变量,这很重要。
t_red1
指的是 t 颜色 red 的终端控制序列,在文件描述符 1.
- 我使用这种表示法是因为它在字符串中的嵌入相对较短,
t_
与其他变量区分开来,尾随的 fd 数字允许每个文件描述符有单独的控制序列(每个文件描述符可能是也可能不是一个终端)。
- 例如,要使用彩色错误消息(在 fd2/stderr 上),您可以添加一行
test -t 2 && t_red2=$'3[31m' t_02=$'3[0m'
.
我正在捕获变量中 command/script 的输出。输出本质上是一个文本块。在这个问题的上下文中,让我们考虑一下:
output='In java, both Errors and Exceptions are the subclasses of some/long/path/to/file.java class. Error refers to an illegal operation at line=23 and executed by app=client
问题: 我喜欢在写入 stdout 之前对部分消息进行着色。我设法找到了一种方法,但有意义/仅适用于一个替代。
color_end=$'[0m'
color_red=$'[31m'
echo "${output//line=/${color_red}LINE=$color_end}"
我也喜欢匹配和着色其他部分(比如 <filename>.java
、app=
)。我尝试在上面的变量替换中使用正则表达式,但是 none 这些工作。出现语法错误或类似错误。
echo "${output//(line=|app=)/${color_red}$color_end}"
尝试使用 sed
,但 1) 颜色会被解释,因此在写入标准输出时 2) 正则表达式模式有点毛茸茸。
实现此目标的最佳方法是什么?
FWIW,所有匹配的部分只有一种颜色。不同的匹配部分没有不同的颜色。
我会这样做:
# Only set colors if printing to a terminal
test -t 1 && t_red1=$'3[31m' t_01=$'3[0m'
# List here the regexes to highlight
echo "$output" |
sed -E 's/[[:alnum:]_]+=|[^[:space:]]+\.java'/"$t_red1&$t_01/g"
- 这可以使用
BASH_REMATCH
在纯 bash 中完成,但sed
更简单,而且可能更有效。 - 文件路径的正则表达式在这里有效,但很脆弱 - 路径中的 space 会破坏它。
- 但您可以使用此模板添加要突出显示的正则表达式。
test -t 1
确保仅当 stdout (fd 1) 是终端时才设置变量,这很重要。t_red1
指的是 t 颜色 red 的终端控制序列,在文件描述符 1.- 我使用这种表示法是因为它在字符串中的嵌入相对较短,
t_
与其他变量区分开来,尾随的 fd 数字允许每个文件描述符有单独的控制序列(每个文件描述符可能是也可能不是一个终端)。 - 例如,要使用彩色错误消息(在 fd2/stderr 上),您可以添加一行
test -t 2 && t_red2=$'3[31m' t_02=$'3[0m'
.