在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
如果未设置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)
没有。
答案 0 :(得分:8)
当我看到你使用它时,我会对此发表评论,但直到现在我才发现问题所在。这条线
IFS=: d=($myvar)
暂时不设置IFS
;它只是在当前shell中设置两个变量。 (简单命令可以使用本地环境设置作为前缀,但赋值语句本身并不是一个简单的命令。)
写作时
echo $IFS
IFS
扩展为:
,但由于:
是IFS
的第一个字符,因此在分词过程中会将其删除。使用
echo "$IFS"
会显示IFS
仍设为:
。
答案 1 :(得分:3)
IFS
在read
的同一行中表现良好:
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")'