2017-01-10 32 views
3

我正在运行Bash版本4.2.25。这里是我的代码:

#!/usr/bin/env bash 

string="one:two:three:four" 

# without quotes 
IFS=: read -ra array_1 <<< $string 
for i in "${array_1[@]}"; do printf "i = [$i]\n"; done 
# output: 
# i = [one two three four] 

# with quotes 
IFS=: read -ra array_2 <<< "$string" 
for i in "${array_2[@]}"; do printf "i = [$i]\n"; done 
# output: 
# i = [one] 
# i = [two] 
# i = [three] 
# i = [four] 

什么解释行为差异?

回答

2

我无法用bash 4.2.46和bash 4.3.30在Linux上重现你的问题。然而,这里的改编版本,它表明所描述的行为:

string="one:two:three:four" 
IFS=: 

read -ra array_1 <<< $string 
for i in "${array_1[@]}"; do printf "i = [$i]\n"; done 
# i = [one two three four] 

read -ra array_2 <<< "$string" 
for i in "${array_2[@]}"; do printf "i = [$i]\n"; done 
# i = [one] 
# i = [two] 
# i = [three] 
# i = [four] 

出现这种情况是因为变量是不实际的空间分割,他们各执$IFS(默认为空格,制表符和换行)。

由于我们已经覆盖$IFS,它的值与冒号我们必须小心引用。空间不再重要。

源代码显示Bash hardcodes a spacestring_list中,通过write_here_string调用。当IFS不包含空格时,扩展为多个单词的字符串将不再沿着类似的行成为令牌read,使差异更加明显。 PS:这是一个很好的例子,说明为什么我们应该总是引用我们的变量,即使我们知道它们包含什么。

1

它看起来像一个错误。我回头看看CHANGES,但找不到任何具体的东西,但是在cygwin bash 4.3.48(8)中,引用和不引用都给出了预期输出(四行)。有时当我有带宽要刻录时,我会克隆repo并指责redir.c以查看是否可以找到一些相关的提交。

+0

这实际上是一个在4.3中部分解决的错误,并在4.4中完成了(?)。 – chepner

相关问题