我正在进行的脚本显示一个多列彩色表格,但颜色代码会干扰格式。颜色代码无法移动到格式字符串,因为某些列的颜色在行与行之间是可变的。相关问答中没有给出解决方案(见下文)。我在下面提供了简化的示例和解决方法。
我的实际用法是一个 bash 脚本,显示一个 11 列的表,其中不同的列具有不同的颜色,是在循环一堆 jpg 文件时生成的,分析各种 exif 数据并将结果输出为表中的一行,其中一些颜色也与行不同根据exif分析结果进行排。
但正如我所说,我在下面提供了简化的解决方法示例。
这是演示该问题的简化显示表片段:
# RedBlk defined in .bashrc.local as RedBlk="^[[0;31;40m"
# DefDef defined in .bashrc.local as DefDef="^[[0m"
(GrnBlk=$(tput setaf 2)
YelBlk="\e[1;33m"
echo "123456789 123456789"
for ii in {8..13}; do
case $ii in
8|9) clr1=""; clr2="";;
11) clr1=$RedBlk; clr2="";;
12) clr1=$YelBlk; clr2=$GrnBlk;;
*) clr1=$GrnBlk; clr2=$RedBlk;;
esac
printf "%6d %6b$DefDef %6b\n" $((ii*2)) $clr1$ii $clr2$((ii*4))
done)
....输出:
123456789 123456789
16 8 32
18 9 36
20 10 40
22 11 44
24 12 48
26 13 52
"^[[0;31;40m"
注意使用or$(tput setaf 2)
或会出现同样的问题"\e[1;33m"
这是一个过于简单的例子:
(echo "123456789 123456789 123456789"
printf "%20s\n" "Hello""Again"
printf "%20s\n" $RedBlk"Hello"$DefDef"Again"
)
....输出:
123456789 123456789 123456789
HelloAgain
HelloAgain
两种解决方法1) 改变字段宽度(例如,在过度简化的示例中从=20
变为= ),以及 2) 拆分字符串并修改格式:20+${#RedBlk}+${#DefDef}
20+10+4
(echo "123456789 123456789 123456789"
printf "%20s\n" "Hello""Again"
printf "%34s\n" $RedBlk"Hello"$DefDef"Again"
printf "%s%15s%s%s\n" $RedBlk "Hello" $DefDef "Again"
)
....输出:
123456789 123456789 123456789
HelloAgain
HelloAgain
HelloAgain
但考虑到实际使用情况,这两种解决方法都非常笨拙。
这些问答虽然相关,但没有提供解决方案:
https://stackoverflow.com/questions/67638971/how-to-get-color-and-width-formatting-with-printf
https://stackoverflow.com/questions/58519511/bash-printf-formated-output-with-colors
https://stackoverflow.com/questions/5412761/using-colors-with-printf
有哪些更简单的解决方案?
这就是我正在使用的:
bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
# which printf
/usr/bin/printf
# /usr/bin/printf --version
printf (GNU coreutils) 8.26
# /usr/bin/xterm -version
XTerm(327)
答案1
一种解决方案是在循环的每次迭代中动态创建格式字符串,如下所示
fmt=`printf "%b" "%6d "$clr1"%6d$DefDef "$clr2"%6d"$DefDef`
printf "$fmt\n" $((ii*2)) $ii $((ii*4))
满的:
(DefDef=$(tput init)
RedBlk=$(tput setaf 1)
GrnBlk=$(tput setaf 2)
YelBlk="\e[1;33m"
echo "123456789 123456789"
for ii in {8..13}; do
case $ii in
8|9) clr1=""; clr2="";;
11) clr1=$RedBlk; clr2="";;
12) clr1=$YelBlk; clr2=$GrnBlk;;
*) clr1=$GrnBlk; clr2=$RedBlk;;
esac
fmt=`printf "%b" "%6d "$clr1"%6d$DefDef "$clr2"%6d"$DefDef`
printf "$fmt\n" $((ii*2)) $ii $((ii*4))
done)
....输出:
123456789 123456789
16 8 32
18 9 36
20 10 40
22 11 44
24 12 48
26 13 52
答案2
另一种解决方案是用相同的长度COLOR_ON(color)
和COLOR_OFF
序列包围每个字段(color
通常是black
)。按照这个长度工作。