4

我正在运行 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]

是什么解释了行为上的差异?

4

2 回答 2

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了 ,因此我们必须小心引用带有冒号的值。空间不再重要。

源代码显示 Bash在 中硬编码一个空格string_list,通过write_here_string 调用。当IFS不包含空格时,扩展为多个单词的字符串将不再read沿相似行进入标记,从而使差异更加明显。

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

于 2017-01-10T20:35:30.727 回答
1

它看起来像一个错误。我回顾了一下CHANGES,找不到任何具体的东西,但是在 cygwin bash 4.3.48(8) 上,带引号和不带引号的都给出了预期的输出(四行)。有时当我有带宽要烧掉时,我会克隆repo并责怪redir.c看看我是否能找到一些相关的提交。

于 2017-01-10T20:21:28.737 回答