为什么echo的输出有差异

为什么echo的输出有差异

我在 Ubuntu 20.04 上使用 Bash 5.0.17

这是后续这个问题。在提出问题之前,我以为我了解如何IFS工作,但现在我完全困惑了,我有一系列问题:

  1. 静态字符串是什么意思?
  2. 分词和扩展有什么区别?
  3. 我在这个网站上的某个地方读到建议引用变量(*),但有时我会得到不同的结果,例如:
IFS=":"; for i in 1:2:3; do echo $i; done # output: 1 2 3
IFS=":"; for i in 1:2:3; do echo "$i"; done # output: 1:2:3

# Why do the quotes make a difference between the two commands?

如果您认为这些问题很愚蠢,请忽略它。如果有人有兴趣帮助我消除这种困惑,我将非常感谢他/她的帮助

谢谢

编辑: 添加了下面的链接


(*):我指的是这两个答案:

答案1

你的for-loop 的行为并不像你想象的那样:

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

$i从字面上看是1:2:3,所以你的循环只运行一次。

IFS仅使用变量扩展或使用命令的特殊变量来分割单词read

这也是你问题的答案。

当您运行 时IFS=:; i=1:2:3; echo $i;,扩展(和单词分割)仅在最后一个命令中发生,并且“单词”(1、2 和 3)分别回显 --> 1 2 3。 (就像 @ikkachu 在他的回答中已经说过的那样,这就是echo行为方式)。
加上引号$i将防止分词,并按echo字面意思输出变量 ( 1:2:3)。


for您还可以利用这些知识通过变量扩展来修复循环:

IFS=:; var=1:2:3; for i in $var; do echo $i; done

将输出:

1
2
3

答案2

我想我已经找到了我的问题的答案(对于最后两个问题,感谢这个网页)。

1.什么是静态字符串?

这不是准确的措辞。但我认为这意味着一个“字面”字符串。

2. 扩展和分词有什么区别?

扩展是指:大括号扩展、波形符扩展、Shell参数和变量扩展(涉及到$符号的使用)、命令替换、算术扩展、过程替换、分词和文件名扩展。

所以分词是扩展的一个特例,引用上面的网页:

shell 扫描未出现在双引号内的参数扩展、命令替换和算术扩展的结果以进行分词。

shell 将 $IFS 的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。如果未设置 IFS,或其值恰好是默认值“''”,则任何 IFS 字符序列都可用于分隔单词。如果 IFS 的值不是默认值,则单词开头和结尾的空白字符“space”和“Tab”序列将被忽略,只要该空白字符位于 IFS 的值中(IFS 空白)特点)。 IFS 中非 IFS 空白的任何字符以及任何相邻的 IF 空白字符共同界定字段。 IFS 空白字符序列也被视为分隔符。如果IFS的值为空,则不会发生分词。

保留显式空参数(“”””或“''”)。由于扩展没有值的参数而产生的不带引号的隐式空参数将被删除。如果没有值的参数在双引号内展开,则会产生空参数并被保留。

但要记住的重要一点是:

相关内容