我在 Ubuntu 20.04 上使用 Bash 5.0.17
这是后续这个问题。在提出问题之前,我以为我了解如何IFS
工作,但现在我完全困惑了,我有一系列问题:
- 静态字符串是什么意思?
- 分词和扩展有什么区别?
- 我在这个网站上的某个地方读到建议引用变量(*),但有时我会得到不同的结果,例如:
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的值为空,则不会发生分词。
保留显式空参数(“”””或“''”)。由于扩展没有值的参数而产生的不带引号的隐式空参数将被删除。如果没有值的参数在双引号内展开,则会产生空参数并被保留。
但要记住的重要一点是: