为单个语句设置IFS

时间:2015-10-29 14:24:45

标签: bash ifs

GNU bash, version 4.3.42(1)-release我正在对answer a question进行一些测试。我们的想法是将: - 分隔的字符串及其每个元素拆分成一个数组。

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

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

显然IFS仍然是相同的:

$ echo $IFS
                      # empty

BASH reference说:

  

如果未设置IFS,则参数以空格分隔。如果IFS是   null,参数在没有插入分隔符的情况下连接。

然而,我注意到IFS有点破碎,因此echo $myvar会返回a b c而不是a:b:c

取消设定值可以解决问题:

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

但我想知道:造成这种情况的原因是什么?是否IFS=: command仅在正在执行的命令范围内更改IFS

我在Setting IFS for a single statement中看到这确实有效:

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

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

3 个答案:

答案 0 :(得分:8)

当我看到你使用它时,我会对此发表评论,但直到现在我才发现问题所在。这条线

IFS=: d=($myvar)

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

写作时

echo $IFS

IFS扩展为:,但由于:IFS的第一个字符,因此在分词过程中会将其删除。使用

echo "$IFS"

会显示IFS仍设为:

答案 1 :(得分: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

答案 2 :(得分: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")'