在组命令中更改$ IFS是永久的

时间:2019-06-28 11:49:05

标签: bash

这是使用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有联系。

3 个答案:

答案 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[*]}"; )