IFS=: 在循环以冒号分隔的值时导致不同的行为
IFS=: leads to different behavior while looping over colon-separated values
实验 1
这是我在名为 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
实验 3
这是我的第三个脚本。
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo
bar
baz
为什么三种情况的输出都不一样?你能解释一下吗
IFS 解释背后的规则和导致的命令
这种不同的输出?
我发现这是一个非常有趣的实验。
谢谢你。
要了解正在发生的事情,
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.
关键是"results of ..."部分,非常隐蔽。
也就是说,分词发生在某些操作的结果上,
如那里所列:参数扩展的结果,
命令替换的结果,等等。
不对 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
.
实验二
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
bar
baz
$var
的参数展开后,
使用IFS
的值进行分词,
因此 for
有 3 个值要迭代,foo
、bar
和 baz
。
echo
的行为在这里很简单,
输出是每行一个字。
底线是:不对文字值执行分词。
分词只对某些操作的结果进行。
这并不奇怪。
字符串文字很像用双引号括起来的表达式,您不会期望在 "..."
.
上进行分词
实验 1
这是我在名为 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
实验 3
这是我的第三个脚本。
IFS=:
var=foo:bar:baz
for i in $var
do
echo $i
done
这会产生以下输出。
$ bash foo.sh
foo
bar
baz
为什么三种情况的输出都不一样?你能解释一下吗 IFS 解释背后的规则和导致的命令 这种不同的输出?
我发现这是一个非常有趣的实验。 谢谢你。
要了解正在发生的事情,
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.
关键是"results of ..."部分,非常隐蔽。
也就是说,分词发生在某些操作的结果上,
如那里所列:参数扩展的结果,
命令替换的结果,等等。
不对 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
.
实验二
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 bar baz
$var
的参数展开后,
使用IFS
的值进行分词,
因此 for
有 3 个值要迭代,foo
、bar
和 baz
。
echo
的行为在这里很简单,
输出是每行一个字。
底线是:不对文字值执行分词。 分词只对某些操作的结果进行。
这并不奇怪。
字符串文字很像用双引号括起来的表达式,您不会期望在 "..."
.