我正在尝试创建菜单功能,并且具有以下脚本段,这意味着将逗号分隔的值列表拆分为数组:
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
我在这里缺少什么?
答案 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的推荐。