问题1:我想在运行时获取数组项作为用户输入;打印项目并打印数组长度。这就是我所拥有的:
read -a myarray
echo "array items" ${myarray[@]}
echo "array length" ${#myarray[@]}
在运行时,我给出了以下内容作为输入,
$ ("apple fruit" "orange" "grapes")
输出是,
array items "apple fruit" "orange" "grapes"
array length 4
这是不正确的。
如果我不要求用户输入,而是使用作为代码一部分声明和初始化的数组,因为myarray=("apple fruit" "orange" "grapes")
数组长度回显为 3。所以,看来我对 read 命令的使用不正确。
问题2:如果我在读取命令中添加提示,如下所示,
read -p "enter array items: " myarray
第一项“苹果水果”被打印为水果“并且长度也是错误的。
如果我删除提示并添加 -a,一切都很好。如果我将 a 和 p 结合起来并将其作为 read -ap 给出,则根本不会弹出提示。它等待值,但没有任何消息。为什么会这样呢?有人可以向我解释一下出了什么问题吗?
答案1
问题一:
在您的示例中,read
不从命令行参数获取输入,而是从标准输入获取输入。因此,它接收到的输入不会经过bash
的字符串解析器。相反,它被视为由空格分隔的文字字符串。因此,根据您的输入,您的数组值将变为:
[0]->("apple
[1]->fruit"
[2]->"orange"
[3]->"grapes"
要执行您想要的操作,您需要转义所有空格,以避免分隔符生效。也就是说,您必须在调用后输入以下输入read
:
apple\ fruit oranges grapes
问题 2:为了read
将接收到的输入存储为数组,必须有一个-a
开关,后跟数组名称。所以你需要:
read -a myarray -p "Enter your items"
答案2
shell 的命令行解析器关心双引号和单引号,但read
并不关心(因此它也不会删除它们)。对于read
输入,您需要反斜杠:
apple\ fruit orange grapes
答案3
如果您想让用户使用 shell 引用来分隔元素(而不仅仅是backslash
),在 中zsh
,您可以这样做:
IFS= read -r 'string?Please enter the elements: '
array=("${(@XQ)${(z)string}}")
(z)
$string
就是像 shell 解析器那样分割成元素。Q
从结果单词中删除一级引用X
报告语法中的错误消息@
并使用引号来保存空元素。
这样,用户可以输入以下内容:
'first word' "second word" third\ word $'word\nwith\nnewline' ''
请注意,虽然没有进行扩展,但预期的 shell 代码语法并不限于引用。例如,$(foo bar)
将被解析为单个$(foo bar)
单词,${unclosed
会导致语法错误。用户需要将它们输入为'$(foo)' 'bar)'
, 或“${unknown”。