为什么在bash测试中字符串等于零

时间:2019-02-13 18:33:14

标签: bash testing

我有一个数组,用于生成一个列表,用户可以从中进行选择。

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对此进行了解释。

2 个答案:

答案 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为您处理了无效的输入,而且您不必自己构建菜单。