使用用户输入来确定 for 循环迭代的次数

使用用户输入来确定 for 循环迭代的次数

我在让 for 循环以我创建的函数的参数形式获取用户输入时遇到了困难。

#!/bin/bash
number1="$1"    #Assume user input 5
loops="$2"      #Assume user input 5
if [[ ${number1} && ${loops} =~ ^-?[0.00-9.99]+$ ]];then
   for number2 in {1..${loops}}
   do
       Product=$(echo "${number1} * ${number2}" | bc -l)
       echo "${number1} * ${number2} = ${Product}"
       if test ${number2} -eq 7;then
           { echo "----------------------"; echo "${number2} is the best number."; echo "----------------------"; continue; }
       elif test ${number2} -eq 11;then
           { echo "------------------------------"; echo "${number2} is pretty awesome as well."; echo "------------------------------"; continue; }    
       fi 
   done
else
   { echo "Please try again with a valid numerical entry."; exit 1; }
fi

当用户为变量“loops”输入一个整数,并为“number1”输入任何数字时,此脚本不会运行。在这种情况下,number1 = 5。它返回错误:

(standard_in)1:语法错误

5 * {1..5} =

/home/$USER/For_Loop_Multiplication.sh:第 9 行:测试:{1..5}:预期整数表达式

/home/$USER/For_Loop_Multiplication.sh:第 11 行:测试:{1..5}:预期整数表达式

如果我直接在脚本中输入循环数的结束界限(如下所示),并且number1 = 5,那么它可以正常运行:

#!/bin/bash
number1="$1"     #Assume user input 5
if [[ ${number1} =~ ^-?[0.00-9.99]+$ ]];then
   for number2 in {1..5}
   do
       Product=$(echo "${number1} * ${number2}" | bc -l)
       echo "${number1} * ${number2} = ${Product}"
       if test ${number2} -eq 7;then
           { echo "----------------------"; echo "${number2} is the best number."; echo "----------------------"; continue; }
       elif test ${number2} -eq 11;then
           { echo "------------------------------"; echo "${number2} is pretty awesome as well."; echo "------------------------------"; continue; }    
       fi 
   done
else
   { echo "Please try again with a valid numerical entry."; exit 1; }
fi

返回结果:

5 * 1 = 5

5 * 2 = 10

5 * 3 = 15

5 * 4 = 20

5 * 5 = 25

本质上,我认为正在发生的事情是,脚本似乎将整个范围作为值 number2 放置,该值被定义为 for 循环中的迭代器。由于变量“loops”的输入是整数,因此在编写脚本时,向用户询问范围并将其放入循环中与简单地将其设置为默认值之间应该没有区别。但是,显然存在区别... 任何有关解决此问题的见解都值得赞赏。谢谢。

答案1

问题出在这一行:

for number2 in {1..${loops}}

这是一个优先顺序问题。如 中所述man bash

扩展的顺序是:括号扩展;波浪号扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);单词拆分;和路径名扩展。

因此,括号扩展发生变量扩展。因此,当括号扩展时,$loops不会被评估为5。这意味着{1..$loops}(您不需要第二个{})扩展为字符串{1..5}而不是从 1 到 5 的数字序列。如果您使用字符串而不是变量,也会发生同样的事情:

$ echo {1..5}  ## works: prints a sequence
1 2 3 4 5
$ echo {1..foo} ## fails: prints a string with no expansion
{1..foo}

作为一种解决方法,您可以使用seq

for number2 in $(seq 1 "$loops"); do ...

或者,更好的是,适合该工作的正确循环:

for((number2=0;number2<=$loops; number2++)); do ...


笔记:作为一般规则,您还应该始终引用您的变量。

相关内容