5

GNU bash, version 4.3.42(1)-release正在做一些测试来回答一个问题。这个想法是将一个 - 分隔的:字符串及其每个元素拆分为一个数组。

为此,我尝试在命令范围内设置IFSto :,以便拆分是自动的并且IFS保持不变:

$ myvar="a:b:c"
$ IFS=: d=($myvar)
$ printf "%s\n" ${d[@]}
a
b
c

显然IFS保持不变:

$回声$IFS
                      # 空的

BASH 参考说:

如果未设置 IFS,则参数以空格分隔。如果 IFS 为空,则将参数连接起来而不插入分隔符。

但是,然后我注意到IFS有点坏了,所以echo $myvar返回a b c而不是a:b:c.

取消设置值可以解决它:

$ unset IFS
$ echo $myvar
a:b:c

但我想知道:是什么原因造成的?不只是在正在执行的命令范围内IFS=: command改变吗?IFS

我在为单个语句设置 IFS 中看到这确实有效:

$ IFS=: eval 'd=($myvar)'
$ echo $myvar
a:b:c

但我不明白为什么它会这样做和IFS=: d=($myvar)不这样做。

4

3 回答 3

8

当我看到你使用它时,我打算对此发表评论,但直到现在我才意识到问题所在。线

IFS=: d=($myvar)

暂时不设置IFS;它只是在当前 shell 中设置两个变量。(简单命令可以以本地环境设置为前缀,但赋值语句本身并不是简单命令。)

当你写

echo $IFS

IFS展开为:,但因为:是 的第一个字符IFS,所以在分词时被删除。使用

echo "$IFS"

将显示IFS仍设置为:.

于 2015-10-29T14:40:14.970 回答
3

IFSread在同一行表现良好:

myvar="a:b:c"
IFS=: read -ra d <<< "$myvar"
printf "%s\n" "${d[@]}"
a
b
c

检查值IFS

declare -p IFS
-bash: declare: IFS: not found

所以显然IFS在当前的shell中没有被篡改。

现在检查原始输入:

echo $myvar
a:b:c

或者:

echo "$myvar"
a:b:c
于 2015-10-29T14:40:07.930 回答
2

在 bash 中,您可以设置一个对单个语句有效的变量,前提是该语句本身不是变量赋值。例如:

$ foo=one bar=two
$ echo $foo
one

要使语句的第二个赋值部分,您需要...一些其他语句。正如您所注意到的,eval有效。此外,read应该工作:

$ foo="one:two:three"
$ IFS=: read -r -a bar <<< "$foo"
$ declare -p bar
declare -a bar='([0]="one" [1]="two" [2]="three")'
于 2015-10-29T14:42:55.560 回答