ifs =:在循环结肠分离值时会导致不同的行为



实验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个值,即迭代foobarbazecho的行为在这里很微不足道,输出是每行单词。


底线是:未对字面价值进行单词分割。单词分配仅对某些操作的结果进行。

这并不是那么令人惊讶。字符串文字很像写在双重引用中的表达式,您不会期望在 "..."上划分单词。

最新更新