颜色代码搞乱了 printf 到 xterm 的表格格式

颜色代码搞乱了 printf 到 xterm 的表格格式

我正在进行的脚本显示一个多列彩色表格,但颜色代码会干扰格式。颜色代码无法移动到格式字符串,因为某些列的颜色在行与行之间是可变的。相关问答中没有给出解决方案(见下文)。我在下面提供了简化的示例和解决方法。

我的实际用法是一个 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

有颜色代码时如何使用 printf 和 %s?

有哪些更简单的解决方案?

这就是我正在使用的:

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)。按照这个长度工作。

相关内容