在Bash中将分隔的字符串解析为数组 - 为什么“$ var”与$ var不同但$ var没有空格?

时间:2017-01-10 20:07:13

标签: bash ifs

我正在运行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 个答案:

答案 0 :(得分:3)

我无法使用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,因此我们必须谨慎引用冒号。空间不再重要。

源代码显示string_list中的Bash hardcodes a space,通过write_here_string调用。当IFS不包含空格时,扩展为多个单词的字符串将不再read成为类似行的标记,从而使差异更明显。

PS:这是一个很好的例子,说明为什么我们应该总是引用我们的变量,即使我们知道它们包含什么。

答案 1 :(得分:1)

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