我认为普遍认为unset IFS
将IFS恢复为默认值
我找不到以下代码
echo -n "_${IFS}_" | xxd
IFS=':'
echo -n "_${IFS}_" | xxd
unset IFS
echo -n "_${IFS}_" | xxd
echo "${IFS-IFS is unset}"
返回此
0000000: 5f20 090a 5f _ .._
0000000: 5f3a 5f _:_
0000000: 5f5f __
IFS is unset
在我的Ubuntu和Android中 如您所见,IFS实际上是未设置的 提前致谢
答案 0 :(得分:5)
我认为普遍认为未设置
IFS
会将IFS
恢复为默认值。
这是完全错误的,在任何文件中都没有提到这一点!
让我们在the reference manual中搜索IFS
,看看我们可以学到什么:
*
($*
)从1开始扩展到位置参数。当扩展不在双引号内时,每个位置参数都会扩展为单独的单词。在执行它的上下文中,这些单词受到进一步的单词拆分和路径名扩展的影响。当扩展发生在双引号内时,它会扩展为单个单词,每个参数的值由IFS
特殊变量的第一个字符分隔。也就是说,$*
相当于$1c$2c…
,其中c
是IFS variable
值的第一个字符。 如果未设置IFS
,则参数以空格分隔。如果IFS
为空,则参数将在不插入分隔符的情况下连接。
试一试:
$ set -- one two three
$ IFS=hello
$ echo "$*"
onehtwohthree
$ unset IFS
$ echo "$*"
one two three
$
类似数组的扩展会发生类似的扩展:"${array[*]}"
和"${!prefix*}"
。
shell将
$IFS
的每个字符视为分隔符,并将其他扩展的结果拆分为使用这些字符作为字段终止符的单词。 如果IFS
未设置,或其值正好为<space><tab><newline>
,则默认为,然后是<space>
,<tab>
和{{1}的序列在前一个扩展的结果的开头和结尾被忽略,并且任何不在开头或结尾的<newline>
个字符序列都用于分隔单词。
也许混淆来自粗体部分。
IFS
内置的参考也引用了这一部分,因此我们不会在那里学到任何新东西。 read
的其他提及不会给图片带来任何新的东西。
不,取消设置IFS
不会将其重置为默认值。手册中的任何地方都没有提到这一点。令人困惑的是,手册指定,对于单词拆分(以及类似数组的参数的IFS
形式),未设置的*
产生的行为与默认值{{1 }}
答案 1 :(得分:3)
引用POSIX / http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05:
如果 IFS 的值是&lt; space&gt;,&lt; tab&gt;和&lt; newline&gt;,或者它是未设置的,...
这并不意味着取消设置IFS
会自动将其重置为IFS
。它只是意味着如果您取消设置IFS
,则会将" \t\n"
设置为IFS
,从而完成分词。
答案 2 :(得分:0)
我也看到一些人的帖子说,如果您取消设置IFS,则会将其恢复为默认值。这里的其他答案有助于澄清故事...
在实际使用的基础上,我想补充一点,我没有在 上观察到与op报告相同的在Ubuntu和Droid上的情况。我在Ubuntu 18中针对/bin/sh
进行了测试,它按预期工作(就像已将还原还原为空白字符一样)。但是,在Yocto(另一个Linux发行版)上,使用/bin/sh
等同于BusyBox(就像您在Droid上找到的一样),unset IFS
使其像设置为NULL
一样工作,即参数在函数等中接收时,它们之间没有定界符。
为解决这个问题,我定义了一个“常量” DEFAULT_IFS=$' \t\n'
,并为其分配了IFS,而不是使用unset
。该方法对我来说适用于各种情况。