为什么shell printf在不加引号的情况下一起运行字符串?

时间:2019-06-10 20:45:40

标签: shell printf posix

有人可以在shell脚本中解释此行为吗?

TESTVAR='something fishy'
echo $TESTVAR
something fishy

但是

printf "%b" $TESTVAR
somethingfishy            (space removed)

printf "%b" "$TESTVAR"
something fishy

为什么会这样?

1 个答案:

答案 0 :(得分:3)

此行为是两个规则的结果:

  • 当您传递的printf参数比格式字符串包含的占位符多时,将重复格式字符串,直到消耗完所有参数为止。对于只有一个占位符的格式字符串,这意味着它将在每个后续参数中重复一次。

  • 不引用参数扩展时,它们会进行单词拆分(在IFS中每个字符的两边为内容创建一个单独的单词)和全局扩展(用列表替换这些单词)解释为glob(如果存在任何这样的名称,则它们匹配的文件名),因此产生了数量不等的shell字,每个shell字作为单独的参数传递给printf


因此,TESTVAR='something fishy'; echo $TESTVAR(默认为IFS)与echo "something" "fishy"精确等效,后者会打印something fishy,因为echo用一个逗号分隔每个参数。空间。

相反,printf %b $TESTVAR变成printf %b "something" "fishy",它使用%b格式化something,并再次格式化fishy;那里什么也不会插入空格,因此输出不会得到任何空格。 (如果改为printf '%b ' $TESTVAR,您会看到插入了空格)。

最后,printf %b "$TESTVAR"运行printf %b "something fishy";之所以保留该空格是因为它是第三个参数的文字部分,因此,%b格式字符串仅对整个something fishy参数(已包含空格)进行一次评估。


这个故事的教训:总是引用您的扩展。另请参见BashPitfalls #14,详细描述echo $foo本身是否是越野车,除非引用为echo "$foo"。 / p>