覆盖行的脚本的着色输出?
Coloring output of a script that overwrites lines?
我正在使用它为 script/command:
的输出着色
commandWithOutput | sed -r 's/(pattern)/'"${COLOR_RED}"''"${COLOR_DEFAULT}"'/g'
(这将为命令输出中出现的所有字符串“pattern”涂上颜色。)它与传统命令配合得很好。但是,如果 script/command 覆盖其输出中的行(也许这与 terminal/console 的关系不仅仅是标准输出?),例如:
Building project X:
CXX Building file XYZ.cpp... [123/1034]
行为不符合预期。我的 sed 仍然会为输出着色,但覆盖不再起作用,即:
Building project X:
CXX Building file ABC.cpp... [1/1034]
CXX Building file DEF.cpp... [2/1034]
CXX Building file GHI.cpp... [3/1034]
CXX Building file JKL.cpp... [4/1034]
CXX Building file MNO.cpp... [5/1034]
// and so on...
CXX Building file XYZ.cpp... [123/1034]
有没有办法为覆盖行的 script/command 的输出着色?
我尝试了几种不同的想法...IFS=$'\r'
+ OP 的 sed
命令...尝试使用中间管道 (mkfifo
) 处理来自 commandWithOutput
...尝试取消缓冲 stdout and/or stdin ...但(到目前为止)只能得到 awk
解决方案,所以 fwiw ...
注意:我假设 OP 的命令在覆盖一行时生成 \r
;如果不是这种情况,OP 可以尝试将命令的输出通过管道传输到 | od -c
以查看 'end of the line' 处的字符是什么,其想法是使用所述字符代替我的 \r
参考文献(下)。
首先我们将编写一个小脚本来生成一些数据,(重新)打印前几行,然后打印一些 'standalone' 行:
$ cat overwrite
#!/usr/bin/bash
for (( i=1 ; i<="" ; i++ ))
do
printf "this is a test ... ${i}\r"
sleep 1
done
printf "\nanother test output \t and a tab\n"
echo "X."
运行 以上生成以下输出:
$ overwrite 3
this is a test ... 3 << this line is actually printed 3x times with suffixes of '1', '2' and '3'
another test output and a tab
X.
运行 这通过 od
显示前 3 行末尾的 \r
:
$ overwrite 3 | od -c
0000000 t h i s i s a t e s t .
0000020 . . 1 \r t h i s i s a t
0000040 e s t . . . 2 \r t h i s i
0000060 s a t e s t . . . 3 \r \n
0000100 a n o t h e r t e s t o u t
0000120 p u t \t a n d a t a b \n
0000140 X . \n
0000143
我们现在来看一个 awk
解决方案,用于重新着色我们 overwrite
脚本输出中的特定模式 ...
首先,我们将为所需的颜色定义开始和 clear/reset 变量;对于这个练习,我将使用 'red':
$ myred=$(tput setaf 1) # set our highlight color to red
$ myreset=$(tput sgr0) # disable coloring
注意:有几种方法可以定义这些颜色(以及 disable/reset);我会把这个留给 reader 来选择最适合他们环境的东西。
这是我发现的一个 awk
解决方案:
$ overwrite 3 | awk -v ptn="test" -v cstart="${myred}" -v creset="${myreset}" -v RS="[\n\r]" '{ sub(ptn,cstart ptn creset) ; printf [=14=] RT }'
其中:
-v ptn="test"
- 我们想要重新着色字符串 test
的所有实例;我们将把它作为 awk
变量 ptn
传递
-v cstart="${myred}"
- 将我们的高亮颜色代码(红色)分配给我们的 awk
变量 cstart
-v creset="${myreset}"
- 将我们的颜色 clear/reset 代码分配给 awk
变量 creset
-v RS="[\n\r]"
- 将我们的输入记录分隔符重新定义为 \r
或 \n
sub(ptn,cstart ptn creset)
- 将 test
的所有实例替换为 <red> + test + <reset>
printf [=45=] RT
- 打印我们的新行; RT
允许我们使用用于解析此记录的相同 RS
运行 以上生成:
this is a test ... 3 << this line is actually printed 3x times with suffixes of '1', '2' and '3', and the 'test' string printed in red
another test output and a tab << the 'test' string is printed in red
X.
我正在使用它为 script/command:
的输出着色commandWithOutput | sed -r 's/(pattern)/'"${COLOR_RED}"''"${COLOR_DEFAULT}"'/g'
(这将为命令输出中出现的所有字符串“pattern”涂上颜色。)它与传统命令配合得很好。但是,如果 script/command 覆盖其输出中的行(也许这与 terminal/console 的关系不仅仅是标准输出?),例如:
Building project X:
CXX Building file XYZ.cpp... [123/1034]
行为不符合预期。我的 sed 仍然会为输出着色,但覆盖不再起作用,即:
Building project X:
CXX Building file ABC.cpp... [1/1034]
CXX Building file DEF.cpp... [2/1034]
CXX Building file GHI.cpp... [3/1034]
CXX Building file JKL.cpp... [4/1034]
CXX Building file MNO.cpp... [5/1034]
// and so on...
CXX Building file XYZ.cpp... [123/1034]
有没有办法为覆盖行的 script/command 的输出着色?
我尝试了几种不同的想法...IFS=$'\r'
+ OP 的 sed
命令...尝试使用中间管道 (mkfifo
) 处理来自 commandWithOutput
...尝试取消缓冲 stdout and/or stdin ...但(到目前为止)只能得到 awk
解决方案,所以 fwiw ...
注意:我假设 OP 的命令在覆盖一行时生成 \r
;如果不是这种情况,OP 可以尝试将命令的输出通过管道传输到 | od -c
以查看 'end of the line' 处的字符是什么,其想法是使用所述字符代替我的 \r
参考文献(下)。
首先我们将编写一个小脚本来生成一些数据,(重新)打印前几行,然后打印一些 'standalone' 行:
$ cat overwrite
#!/usr/bin/bash
for (( i=1 ; i<="" ; i++ ))
do
printf "this is a test ... ${i}\r"
sleep 1
done
printf "\nanother test output \t and a tab\n"
echo "X."
运行 以上生成以下输出:
$ overwrite 3
this is a test ... 3 << this line is actually printed 3x times with suffixes of '1', '2' and '3'
another test output and a tab
X.
运行 这通过 od
显示前 3 行末尾的 \r
:
$ overwrite 3 | od -c
0000000 t h i s i s a t e s t .
0000020 . . 1 \r t h i s i s a t
0000040 e s t . . . 2 \r t h i s i
0000060 s a t e s t . . . 3 \r \n
0000100 a n o t h e r t e s t o u t
0000120 p u t \t a n d a t a b \n
0000140 X . \n
0000143
我们现在来看一个 awk
解决方案,用于重新着色我们 overwrite
脚本输出中的特定模式 ...
首先,我们将为所需的颜色定义开始和 clear/reset 变量;对于这个练习,我将使用 'red':
$ myred=$(tput setaf 1) # set our highlight color to red
$ myreset=$(tput sgr0) # disable coloring
注意:有几种方法可以定义这些颜色(以及 disable/reset);我会把这个留给 reader 来选择最适合他们环境的东西。
这是我发现的一个 awk
解决方案:
$ overwrite 3 | awk -v ptn="test" -v cstart="${myred}" -v creset="${myreset}" -v RS="[\n\r]" '{ sub(ptn,cstart ptn creset) ; printf [=14=] RT }'
其中:
-v ptn="test"
- 我们想要重新着色字符串test
的所有实例;我们将把它作为awk
变量ptn
传递
-v cstart="${myred}"
- 将我们的高亮颜色代码(红色)分配给我们的awk
变量cstart
-v creset="${myreset}"
- 将我们的颜色 clear/reset 代码分配给awk
变量creset
-v RS="[\n\r]"
- 将我们的输入记录分隔符重新定义为\r
或\n
sub(ptn,cstart ptn creset)
- 将test
的所有实例替换为<red> + test + <reset>
printf [=45=] RT
- 打印我们的新行;RT
允许我们使用用于解析此记录的相同RS
运行 以上生成:
this is a test ... 3 << this line is actually printed 3x times with suffixes of '1', '2' and '3', and the 'test' string printed in red
another test output and a tab << the 'test' string is printed in red
X.