这是我在文件中的第一个名为foo.sh
的脚本。
IFS=:
for i in foo:bar:baz
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo bar baz
这是我的第二个剧本。
IFS=:
for i in foo:bar:baz
do
unset IFS
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo:bar:baz
这是我的第三个脚本。
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo
bar
baz
为什么三种情况下的输出都不同?你能解释清楚吗? IFS解释背后的规则以及导致的命令 这个不同的产出?
答案 0 :(得分:15)
我发现这是一个非常有趣的实验。 谢谢你。
要了解发生了什么,
man bash
的相关部分是:
Word Splitting The shell scans the results of parameter expansion, command substitu- tion, and arithmetic expansion that did not occur within double quotes for word splitting.
关键是“...的结果”部分,它非常微妙。
也就是说,单词拆分发生在某些操作的结果上,
如上所列:参数扩展的结果,
命令替换的结果,等等。
不对字符串文字执行单词拆分,例如foo:bar:baz
。
让我们看看这个逻辑在你的例子的背景下如何发挥作用。
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
。
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
。
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出:
foo bar baz
$var
的参数扩展后,
使用IFS
的值执行单词拆分,
因此for
有3个要迭代的值,foo
,bar
和baz
。
echo
的行为在这里是微不足道的,
输出是每行一个字。
底线是:不对文字值执行单词拆分。 单词拆分仅对某些操作的结果执行。
这并不奇怪。
字符串文字很像用双引号括起来的表达式,你不希望在"..."
上分词。