在while循环中苦苦挣扎,有两个条件和一个for循环

时间:2017-12-06 21:14:12

标签: bash shell

我正在尝试学习如何在bash中使用数组。我正在编写一个脚本,要求用户提供三个数字,并确定最大数字是什么。我希望脚本强制用户只输入数值。而且,我希望这三个数字应该是不同的。我正在使用数组来存储用户输入。这就是我到目前为止所做的:

## declare variables
order=("first" "second" "third")
answers=()
RED='\033[0;31m'
NC='\033[0m' # No Color

numbersonly() {
        if [[ ! $1 =~ ^[0-9]+$ ]]; then
        echo "${RED}$1 is not a valid number.${NC}"
        else
            answers+=("$input")
            break
        fi
}

inarray(){
    for e in ${answers[@]}; do
    if [[ $1 == $e ]]; then
    echo "${RED}Warning.${NC}"
    fi
    done
}

readnumber(){
for i in {1..3}; do
j=$(awk "BEGIN { print $i-1 }")
    while read -p "Enter the ${order[$j]} number: " input ; do      
    inarray $input
    numbersonly $input
    done
done
}

displayanswers(){
echo "Your numbers are: ${answers[@]}"
}

biggestnumber(){

if (( ${answers[0]} >= ${answers[1]} )); then
        biggest=${answers[0]}
        else
        biggest=${answers[1]}
        fi
if (( $biggest <= ${answers[2]} )); then
        biggest=${answers[2]}
        fi  
echo "The biggest number is: $biggest"
}

main(){
readnumber
displayanswers
biggestnumber
}

main

现在,当用户输入之前输入的数字时,我可以让脚本显示警告,但是如果用户输入已经存在,我似乎无法找到保留在while循环中的正确语法进入。想法?

2 个答案:

答案 0 :(得分:0)

我找到了解决方法。我的问题是双重的:1)我没有意识到如果你有一个嵌套在while循环中的for循环,你需要两个break语句来退出while循环; 2)在同一个while循环中有两个函数使得很难控制发生了什么。通过将inarray()和numbersonly()合并到一个新函数中,我解决了双条件问题。新功能如下所示:

testing(){
for item in ${answers[*]}
do
    test "$item" == "$1" && { inlist="yes"; break; } || inlist="no"
done

if [[ $inlist == "yes" ]]; then
echo "${RED}$1 is already in list.${NC}"
else
        if [[ ! $1 =~ ^[0-9]+$ ]]; then
        echo "${RED}$1 is not a valid number.${NC}"
        else
            answers+=("$input")
            break
        fi
fi
}

答案 1 :(得分:-2)

这里没有太多的研究就是从屏幕上跳下来跟随我。当心我还没有真正测试过它......调试是留给学生的一项练习。

建议使用较新的“函数”定义,因为您可以声明局部变量。 ()定义不允许本地化变量。

function inarray
{
    local e;   #don't muck up any variable e in caller
 ...
}

要计算值,请避免额外的awk并使用j=$(( i - 1 ));

biggestnumber应该使用循环。

总体评论:

nummax=3;  #maximum value defined in just one place

# loop this way... showing optional {} trick for marking larger loops
for (( n = 0; n < nummax; ++n )); do
{
     nx=$(( 1 + n ));   #1 based index
} done;

提示:一旦所有输入都存在,应该停止输入循环。还可以添加:

    if [ "" == "${input:-}" ]; then break;
for (( a = 0; a < ${#answer[*]}; ++a )); do

如果变量值为空或包含许多shell元字符(如空格),请注意大量使用双引号以避免语法错误。我不能告诉你我通过在现有代码中添加引号来修复了多少错误报告。

[[...]]表达式使用文件名测试,而不是正则表达式。您可以使用[[ ! $1 =~ ^[0-9]+$ ]];[[ "$1" != [0-9]* ]] && [[ "$1" != *[^0-9]* ]]最近的地方。 但我怀疑 ! expr >/dev/null "$i" : '[0-9][0-9]*$'; 更像是你想要的“expr”使用正则表达式。不要包含在[] s中。使用[0-9] [0-9] *而不是[0-9] +作为“+”在UNIX正则表达式的所有方言中给出了混合成功。