如何将带有格式的 printf 输出存储到变量中?
这是因为您没有引用变量。如果引用了变量,格式将显示完整:
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
不包含数字或-
)。
有关在什么情况下可以省略引号的详细信息,请参阅何时需要双引号?。
除非您确实希望发生所有这些冗长的操作,请记住始终在变量和命令替换周围使用双引号。请注意:省略引号不仅会导致错误,还会导致安全漏洞。