如何为printf动态创建格式设置规则?

时间:2019-03-01 15:19:40

标签: shell formatting printf string-formatting

我正在尝试在30个字符宽度的多列中打印几行:

#!/bin/bash
chars_width=15
full_string="a\\nb\\nc\\nd"
number_of_columns=$(( $(tput cols) / $chars_width ))

for ((i = 0; i < number_of_columns; i++)); do
    formatting_string="$formatting_string%%-"$chars_width"s "
done

echo "$full_string" | xargs -L $number_of_columns | \
    while read -r values
    do
        printf "$formatting_string\\n" $values
    done
exit

运行此程序时,我希望它输出:

a              b              c              d

但是它输出:

%-15s %-15s %-15s %-15s

如何为printf使用动态构建的格式设置规则以供使用?

2 个答案:

答案 0 :(得分:3)

在格式字符串中使用单个'%'字符。您已经逃脱了,所以什么也无法替代。

答案 1 :(得分:1)

您对数据有多信任?您可能要让命令解析器剥离额外的空格,但这会带来一些风险。

$: full_string=$'a\nb\nc\nd'
$: printf %-15s $full_string $'\n'
a              b              c              d

如果您的数据在文件中...

$: r=( $(<file) )
$: printf %-15s "${r[@]}" $'\n'
a              b              c              d

甚至

$: printf %-15s $(<file) $'\n'
a              b              c              d

您可能不会看到的是,换行符也是在15宽的字段中打印的,因此该行的末尾有很多空格。

请注意,这些重复使用了单个格式化字符串(这很简单,我没有引用,但是通常应该这样做)。

将引号放在错误的位置会导致问题...

$:  printf %-15s "$(<file)" $'\n'
a
b
c
d

您会从中获得相同的结果

$: printf %-15s "$full_string" $'\n'

通常,您要想要引用,但是可以通过创造性地将它们排除在外并让解析器操纵空白来完成有用的事情。请注意您所得到的。如果这些字段之一中有嵌入的空格,则所有选择都将关闭。

相同的警告说明也适用于格式本身。

$: f="%-15s %5s"
$: printf $f $x $'\n' # oops!
%5s            a              b              c              d
$: printf "$f" $x $'\n'
a                   bc                   d

因此,您可以根据需要动态创建不同的格式,只需用双引号将变量引起来即可“正确”解析该变量。与往常一样,对其进行测试。