实验1
这是我在文件中的第一个名为 foo.sh
的脚本。
IFS=:
for i in foo:bar:baz
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo bar baz
实验2
这是我的第二个脚本。
IFS=:
for i in foo:bar:baz
do
unset IFS
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo:bar:baz
实验3
这是我的第三个脚本。
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo
bar
baz
为什么输出在所有三种情况下都不同?你能解释一下解释IFS的规则和导致的命令这不同的输出?
我发现这是一个非常有趣的实验。谢谢你。
了解发生了什么,man bash
的相关部分是:
单词分裂 外壳扫描参数扩展的结果,命令替换 - 在双引号中没有发生的算术和算术扩展 用于单词分开。
关键是" ...的结果" 部分,它非常微妙。也就是说,单词分割发生在某些操作的结果上如那里所列出的:参数扩展的结果,命令替代的结果,依此类推。在诸如 foo:bar:baz
的字符串文字上不执行单词分配。
让我们看看这种逻辑在示例的上下文中如何发挥作用。
实验1
IFS=:
for i in foo:bar:baz
do
echo $i
done
这会产生以下输出:
foo bar baz
在字面的foo:bar:baz
上执行没有单词拆分,因此,IFS
的值是什么,就for
循环而言。
在参数扩展后,对$i
的值进行了单词分割,因此foo:bar:baz
分为3个单词,并传递给echo
,因此输出为foo bar baz
。
实验2
IFS=:
for i in foo:bar:baz
do
unset IFS
echo $i
done
这会产生以下输出:
foo:bar:baz
再次在字面的foo:bar:baz
上没有执行任何单词分配,因此,IFS
的值是什么,就for
循环而言。
在参数扩展后,对$i
的值进行了单词分割,但是由于IFS
不设置,其默认值用于执行拆分,是<space><tab><newline>
。但是由于foo:bar:baz
不包含其中任何一个,它保持完整,因此输出为foo:bar:baz
。
实验3
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出:
foo酒吧baz
$var
的参数扩展之后使用IFS
的值执行单词分配因此,for
具有3个值,即迭代foo
,bar
和baz
。echo
的行为在这里很微不足道,输出是每行单词。
底线是:未对字面价值进行单词分割。单词分配仅对某些操作的结果进行。
这并不是那么令人惊讶。字符串文字很像写在双重引用中的表达式,您不会期望在 "..."
上划分单词。