我有一个包含一些元素的数组,并且在某些函数中包含以下内容:
echo -n "Select the option: "
read option
echo "option: '${option}'"
echo "option: '$option'"
if [[ $option -ge 1 && option -le ${#array[@]} ]]; then
echo "go go go"
...
else
...
fi
关于输入 - 如果写入的数字高于数组的长度/大小,则该else
块将按预期执行 - 与负数相同 - 或什至0
。到这里一切都在预料之中
但如果写入一个简单的字符,如s
,则执行该块,并且它是d
if
不是预期的。
select the option: d
option: 'd'
option: 'd'
go go go
根据我的理解-ge
,它-le
应用于数字 - 所以如果使用字符如何进行数字比较,它应该失败 - 它应该直接进入else
块
如何解决这个问题?
答案1
这里发生的事情(对你来说)是一个意想不到的评价。作为参考,这是您的原始表达
[[ $option -ge 1 && option -le ${#array[@]} ]]
首先,$option
进行评估。在本例中是d
.然后将其代入[[ … ]]
表达式以获得:
[[ d -ge 1 && option -le 12 ]]
这是评价的。但是因为[[ … ]]
使用bash
的表达式求值d
和option
被视为变量的名称,所以还有另一个级别的扩展(隐式地意识到这一点d=0
):
[[ 0 -gt 1 && d -le 12 ]]
第一部分失败,因此跳过第二个(错误的)表达式。
您可以考虑以下几种解决方案:
而不是使用
[[ … ]]
旧的但可以接受的[ … ]
。这不会执行这种双重扩展。但是,当不是数字时,这不会捕获“非数字”错误$option
,因此您仍然会收到错误[ "$option" -ge 1 ] && [ "$option" -le ${#array[@]} ]
通过验证字符串中的字符仅为数字来保护表达式比较。
[[ "$option" =~ ^(0|([1-9][0-9]*))$ && "$option" -ge 1 && "$option" -le "${#array[@]}" ]]