为什么我的列表被删除了逗号?

时间:2016-03-09 04:42:46

标签: bash shell

我正在尝试创建菜单功能,并且具有以下脚本段,这意味着将逗号分隔的值列表拆分为数组:

IFS=,
read -r -a optionList <<< $3

但是,结果始终是单个条目,没有逗号

echo ${#optionList[@]}
echo ${optionList[0]}

给出如下所示的输出:

1
Option 1 Option 2 Option 3

然而,以下是预期的:

echo $3

产生的输出为:

Option 1,Option 2,Option 3

我在这里缺少什么?

3 个答案:

答案 0 :(得分:3)

引用变量$3

当您设置IFS会话时,并且不引用任何变量时,该变量将根据此IFS,的值进行单词拆分。案件)。这是由shell在read获取变量值之前完成的,因此read得到Option 1 Option 2 Option 3而不是期望Option 1,Option 2,Option 3来操作:

$ IFS=,; echo $bar
Option 1 Option 2 Option 3

$ IFS=,; echo "$bar"
Option 1,Option 2,Option 3

解决您的问题:

$ echo $bar
Option 1 Option 2 Option 3


#### Without quoting

$ IFS=, read -ra foo <<< $bar

$ echo "${#foo[@]}"
1

$ echo "${foo[0]}"
Option 1 Option 2 Option 3


#### With Quoting

$ IFS=, read -ra foo <<< "$bar"

$ echo "${#foo[@]}"
3

$ echo "${foo[0]}"
Option 1

$ echo "${foo[1]}"
Option 2

$ echo "${foo[2]}"
Option 3

答案 1 :(得分:2)

您可以将IFS内联使用:

str='Option 1,Option 2,Option 3'
IFS=, read -ra optionList <<< "$str"

这样可以避免损坏当前shell的IFS

检查输出:

declare -p optionList
declare -a optionList='([0]="Option 1" [1]="Option 2" [2]="Option 3")'

答案 2 :(得分:2)

这里有两个基本问题:设置IFS会影响shell解析字符串的很多方面,包括你不期待的一些问题;并且$3不加引号可以让它成为搞乱的事情之一。

发生的事情是,当你引用$3时没有双引号时,shell将其拆分为&#34; words&#34;使用$IFS作为分隔符。在您的示例中,这会产生三个字:&#34;选项1&#34;,&#34;选项2&#34;和&#34;选项3&#34;。在<<<的上下文中,然后使用空格作为分隔符将它们拼接在一起(这很奇怪,但这就是它的作用),产生&#34;选项1选项2选项3&# 34 ;.你可以分别看到这个效果:

$ foo="Option 1,Option 2,Option 3"
$ IFS=,
$ cat <<< $foo
Option 1 Option 2 Option 3

然后read命令获得&#34;选项1选项2选项3&#34;作为输入,基于$IFS(&#34;,&#34;)拆分它,发现没有单词分隔符,因此它将它全部放在optionList的元素#0中。

您可以通过重复引用$3来解决这个问题,以防止分词,但是您会遇到其他问题,因为IFS也会影响您的其他许多事情。脚本。所以你应该 遵循anubhava的建议,使IFS赋值在read命令上作为前缀,这样它只影响那一个命令< / em>而不是对shell如何解析字符串的全局更改。

因此,对于这两项更改,我的建议是使用:

IFS=, read -ra optionList <<< "$3"

......就像anubhava的推荐。