这是使用bash 4.3.48。
$ ARR=(entry1 entry2 entry3)
$ echo "${ARR[*]}"
entry1 entry2 entry3
一切正常,直到这里,但之后
$ { IFS=: ; echo "${ARR[*]}" ;}
entry1:entry2:entry3
在更改后,IFS被奇怪地永久性地更改了一半
$ echo "${ARR[*]}"
entry1:entry2:entry3
$ echo $IFS
$ echo "$IFS"
:
由于我无法理解这种行为,因此我认为这是一个错误。可能与IFS change with Bash 4.2有联系。
答案 0 :(得分:5)
$ echo $IFS $ echo "$IFS" :
编写不带双引号的变量扩展会使其受到单词拆分(和遍历)的影响。单词拆分通过$IFS
中的字符将字符串拆分。当您编写$var
时,好像有一个隐藏的函数调用split+glob($var)
。
如果您考虑一下,写$IFS
不用引号注定会失败。它用$IFS
中的字符分割$IFS
。多么元。无论将$IFS
设置为什么,结果都是一个空字符串
$ (IFS='abc'; echo $IFS)
$ (IFS='<>'; echo $IFS)
$ (IFS='!@#$'; echo $IFS)
课程:始终引用变量扩展名。
$ (IFS='abc'; echo "$IFS")
abc
$ (IFS='<>'; echo "$IFS")
<>
$ (IFS='!@#$'; echo "$IFS")
!@#$
答案 1 :(得分:2)
{ ... ; }
在当前shell的上下文中运行命令。花括号内更改的$ IFS(或任何其他变量)即使在花括号后也保持其值。
要本地化变量的更改,请使用子外壳(圆括号):
(IFS=:; echo "${arr[*]}")
echo $IFS
不输出冒号的原因是不同的。实际上,在将$ IFS设置为:
之后,任何包含:
的变量都将显示为空:
IFS=:
x=:
echo $x # Nothing!
这是因为不带双引号的变量会进行单词拆分,该拆分使用$ IFS定义分隔符。
x=a:b:c
echo $x # a:b:c
IFS=:
echo $x # a b c
在第二种情况下,echo具有三个参数。 echo $IFS
时,无论$ IFS当前值是多少,都没有参数。
答案 2 :(得分:2)
{ ... }
不在子Shell中运行。因此,{ .. }
中的所有更改都在 current 外壳中可见。
{ a=1; }; echo $a
其中包括IFS。您已设置IFS=:
,并且更改保留在大括号后面。
{ IFS=:; }; echo "$IFS"
现在我们开始扩展,word splitting。这就是为什么无论将IFS设置为以下什么都将始终显示空白行的原因:
echo $IFS
IFS本身是分隔符。上面的echo
收到一个为空的参数。 echo $IFS
等同于echo ''
。示例:尝试一下,将显示以下内容:
IFS=@; echo Hello${IFS}world
要打印IFS值,必须用引号引起来,否则它将充当分词器。
在IFS中打印以第一个字符分隔的数组成员的方法是使用子外壳( .. )
:
( IFS=:; echo "${arr[*]}"; )