为什么设置IFS时echo和printf的输出不一样

为什么设置IFS时echo和printf的输出不一样

我在 Ubuntu 20.04 上使用 Bash 5.0.17

当我运行以下命令时:

IFS=":"; for i in "1:2:3"; do echo $i; done
# output is: 1 2 3

IFS=":"; for i in "1:2:3"; do echo "$i"; done
output is: 1:2:3

IFS=":"; for i in "1:2:3"; do printf "%s\n" $i; done
# output is: 
# 1
# 2
# 3

IFS=":"; for i in "1:2:3"; do printf "%s\n" "$i"; done
# output is: 1:2:3

这让我很困惑。

  1. 为什么不将echo每个标记打印在单独的行中?
  2. 为什么在没有引用的情况下却能printf按预期工作?$i
  3. 为什么引用时echoand都会失败?printf$i

我感谢您的帮助

答案1

循环for i in "1:2:3"; do ...只运行一次。静态文字字符串没有分词,只有扩展,甚至只有不带引号的扩展。你会看到不同的结果,例如

IFS=:
var="1:2:3"
for i in $var; do...

剩下的就是如何echoprintf工作。echo用空格连接参数,并打印连接后的字符串,后跟一个换行符。但printf根据需要多次重复格式字符串以容纳所有参数,因此您会得到多个换行符。

因此,在第一个中,echo $i运行 i设置为1:2:3。扩展未加引号,因此将其拆分,并echo获取三个参数1, 2, 3。它将它们与空格连接起来,给出1 2 3,输出是加上换行符。这和跑步是一样的echo 1 2 3。 (甚至是echo 1 2 "3",因为 shell 命令行上未加引号的空格数量并不重要。)

第三个与 类似printf "%s\n" 1 2 3,并且重复格式字符串,输出分三行。类似的东西printf "%s %s\n" 1 2 3每次重复都会使用两个参数,并会1 2在一行和3另一行上打印。

相关内容