如何将带有格式的 printf 输出存储到变量中?

18 浏览
0 Comments

如何将带有格式的 printf 输出存储到变量中?

我想要将带有格式的printf的输出存储到一个变量中,但是出于某种原因,它去掉了格式。

这是正确的输出:

$ printf "%-40s %8s %9s  %7s" "文件系统" "可用空间" "参考配额" "可用空间百分比"
文件系统                                        可用空间   参考配额     可用空间百分比

现在格式已经被去掉了:

$ A=$(printf "%-40s %8s %9s  %7s" "文件系统" "可用空间" "参考配额" "可用空间百分比")
$ echo $A
文件系统 可用空间 参考配额 可用空间百分比

0
0 Comments

问题原因:在使用echo命令时,它会按顺序打印每个参数,并用一个空格分隔。你正在向echo传递一系列不同的参数。

解决方法:简单的解决方法是引用$A变量:

A=$(printf "%-40s %8s %9s  %7s" "File system" "Free" "Refquota" "Free %")
echo "$A"

这样,printf函数的输出结果将存储在变量A中,并通过引用变量A来打印输出。

0
0 Comments

这是因为您没有引用变量。如果引用了变量,格式将显示完整:

echo "$A"   #虽然最好使用$a,但大写变量不是一个好习惯

也就是说,您的var=$(printf )方法完全正确,只是您没有正确使用echo

您可能想知道为什么。请在为什么我的Shell脚本在空格或其他特殊字符上出错?中找到答案。

为什么我需要写"$foo"?没有引号会发生什么?

$foo并不意味着“取变量foo的值”。它意味着更复杂的事情:

  • 首先,取变量的值。*字段分割:将该值视为以空格分隔的字段列表,并构建结果列表。例如,如果变量包含foo * bar,则此步骤的结果是3元素列表foo*bar

    • 文件名生成:将每个字段视为全局通配符,即通配符模式,并将其替换为与此模式匹配的文件名列表。如果模式不匹配任何文件,则保持不变。在我们的示例中,这将导致列表包含foo,后跟当前目录中的文件列表,最后是bar。如果当前目录为空,则结果是foo*bar

请注意,结果是一个字符串列表。Shell语法中有两个上下文:列表上下文和字符串上下文。字段分割和文件名生成仅在列表上下文中发生,但这是大部分情况。双引号限定了一个字符串上下文:整个双引号字符串是一个单独的字符串,不会被分割。(例外情况:"$@"扩展为位置参数列表,例如,如果有三个位置参数,则"$@"等效于"$1" "$2" "$3"。请参阅什么是$*和$@之间的区别?

命令替换$(foo)`foo`也会发生同样的情况。顺便说一下,不要使用`foo`:它的引号规则很奇怪和不可移植,并且所有现代Shell都支持直观的引号规则的$(foo)

算术替换的输出也会进行相同的扩展,但这通常不是一个问题,因为它只包含不可扩展的字符(假设IFS不包含数字或-)。

有关在什么情况下可以省略引号的详细信息,请参阅何时需要双引号?

除非您确实希望发生所有这些冗长的操作,请记住始终在变量和命令替换周围使用双引号。请注意:省略引号不仅会导致错误,还会导致安全漏洞

0