我有一个数组,用于生成一个列表,用户可以从中进行选择。
list=(a b c d)
n=0
for x in ${list[@]}
do echo $n\)$x
n=$((n++)
done
read -p "Pick an item:" choice
我只想选择有效的选项,所以我要像这样检查。
if [[ $choice -gt ${#list[@]} && $choice -lt -1 ]]
then ...
else
echo "not a valid choice"
我遇到的问题是所有字符串的评估结果均等于零。即[[ "I am a duck" -eq 0 ]]
是True,(( "I am a duck" == 0 ))
也是如此。有没有办法使所有字符串和数字比较的结果都为false?我知道我可以使用[[ $choice =~ [A-Za-z]+ ]]
检查一个字符串,但是我想知道是否有没有正则表达式的方法吗?
编辑 抱歉,在放下“我是鸭子”这句话之前,我应该已经对其进行了测试。它不喜欢空格。但是,“ I_am_a_duck”的计算结果确实为0。下面的chepner对此进行了解释。
答案 0 :(得分:2)
-gt
,因为它旨在比较整数,所以触发了与算术表达式中所示字符串相同的行为:将字符串视为参数的名称,然后对该参数进行扩展(重复该过程如有必要),直到得到整数为止。如果没有该名称的参数,则用0代替。
也就是说,您可以通过编号从1开始并使用
来解决问题。if (( choice < 1 || choice > ${#list[@]} )); then
echo "not a valid choice"
因为现在任何非整数输入都将被视为0,实际上小于下限1。
答案 1 :(得分:1)
我会为此使用select
,而根本不处理算术上下文中字符串的行为(如chepner的回答所述):
list=(a b c d)
PS3='Pick an item: '
select opt in "${list[@]}"; do
case $opt in
[abcd]) echo "Choice: $opt ($REPLY)" ;;
*) echo "Illegal choice" ;;
esac
done
这将继续循环;要在进行有效选择后继续,则必须在某个地方放置break
。主要好处是select
为您处理了无效的输入,而且您不必自己构建菜单。