带有嵌套循环的嵌套 if 语句

时间:2021-04-13 09:14:43

标签: linux bash if-statement nested-loops

我正在尝试制作一个简单的计算器。我敢肯定,如果你只是看一眼这段代码,你就会明白我在做什么。 输入一个数字,然后选择一个操作数,然后 vim 应该打印出一个最多 15 的表格,其中包含您的数字和操作数...

也许这个方法很愚蠢,试图在嵌套的 if 语句中嵌套大量循环。但我是 bash 新手。

错误是第 24 行“在 else 附近出现意外标记”,但我觉得我不理解的嵌套存在根本问题。

这是当前代码。

#!/bin/bash
choice=6
read -p "Enter a number bruv" num
#choose operand.
echo "Now choose an operand comrade"
#choices

echo "1. *"
echo "2. +"
echo "3. -"
echo "4. /"
echo "5. ^"

echo -n "Please choose [1,2,3,4,5]"

while [ $choice -eq 6 ]; do
        read choice

        if [ $choice -eq 1 ] ; then
                for((i=0;i<=15;i++))
                do
                echo -n "$i * $num = $[ $i * $num ] "
                echo " "
        else
                if [ $choice -eq 2 ] ; then
                        for((i=0;i<=15;i++))
                        do
                        echo -n "$i + $num = $[ $i + $num ] "
                        echo " "
                else
                        if [ $choice -eq 3 ] ; then
                                for((i=0;i<=15;i++))
                                do
                                echo -n "$i - $num = $[ $i - $num ] "
                                echo " "
                        else
                                if [ $choice -eq 4 ] ; then
                                        for((i=0;i<=15;i++))
                                        do
                                        echo -n "$i / $num = $[ $i / $num ] "
                                        echo " "
                                else
                                        if [ $choice -eq 5 ] ; then
                                       for((i=0;i<=15;i++))
                                        do
                                        echo -n "$i ^$num = $[ $i ^$num ] "
                                        echo " "
                                else echo "Please choose between 1 and 5!!!"
                                          echo "1. *"
                                         echo "2. +"
                                          echo "3. -"
                                          echo "4. /"
                                           echo "5. ^"
                                        echo -n "Please choose [1,2,3,4,5]"
                              fi
                     fi
             fi
        fi
     fi
done


                                                                       

实施这个会更好吗?

# !/bin/bash
  
# Take user Input
echo "Enter number : "
read a

  
# Input type of operation
echo "Enter Choice :"
echo "1. Addition"
echo "2. Subtraction"
echo "3. Multiplication"
echo "4. Division"
echo "5. Power"
read ch
  
# Switch Case to perform
# calulator operations
case $ch in
  1)res=`for((i=0;i<=15;i++))
                                do
                                echo -n "$i - $num = $[ $i - $num ] "
                                echo " "`
  ;;
  2)res=`for((i=0;i<=15;i++))
                                do
                                echo -n "$i - $num = $[ $i - $num ] "
                                echo " "`
  ;;
  3)res=`for((i=0;i<=15;i++))
                                do
                                echo -n "$i - $num = $[ $i - $num ] "
                                echo " "`
  ;;
  4)res=`for((i=0;i<=15;i++))
                                do
                                echo -n "$i - $num = $[ $i - $num ] "
                                echo " "c`
  ;;
esac
echo "Result : $res" ```

2 个答案:

答案 0 :(得分:1)

这是一个解决方案,使用一个函数:

#! /bin/bash

ITER_MAX=15

show_values() # n op
{
    local n=$1 op=$2
    for ((i=0; i<=ITER_MAX; i++)); do
        ((i>0)) && echo -n " ; "
        echo -n "$i $op $n = $((i $op n))"
    done
    echo
}

# Take user Input
read -p "Enter number : " a

# Input type of operation
echo "Enter Choice (Ctrl+C to stop):"
PS3=">> "
select ch in Addition Subtraction Multiplication Division Power ; do
  case "$ch" in
    Add*) op="+" ;;
    Sub*) op="-" ;;
    Mul*) op="*" ;;
    Div*) op="/" ;;
    Pow*) op="**" ;;
    *) echo "Bad choice, abort" >&2 ; break ;;
  esac
  show_values "$a" "$op"
done

一些解释:

  • (( )) 是算术计算,$(( )) 是算术展开
  • ((i>0)) && echo -n " ; " 等价于 if ((i>0)); then echo -n " ; " ; fi
  • read -p "Enter number : " a 等价于 echo -n "Enter number : " ; read a
  • 关于 select,请参阅 bash 终端中的 help select

答案 1 :(得分:0)

使用https://www.shellcheck.net/

 
Line 20:
                for((i=0;i<=15;i++))
                ^-- SC1009: The mentioned syntax error was in this for loop.
                   ^-- SC1073: Couldn't parse this arithmetic for condition. Fix to allow more checks.
 
Line 21:
                do
                ^-- SC1061: Couldn't find 'done' for this 'do'.
 
Line 24:
        else
        ^-- SC1062: Expected 'done' matching previously mentioned 'do'.
            ^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.

另一种选择:

read -p "Enter a number and an operator: " -a a
for n in {1..15}; do printf "%+10s\n" $((${a[@]} $n)); done

-p 告诉 read 提供提示。 -a 读入数组(此处命名为 a)。
{1..15} 是内置的 bash 序列语法。
%+10s 告诉 printf 用空格键/右对齐到 10 个字符。
${a[@]} 替换为数组的所有元素 - 数字和运算符。
$(( ... )) 进行算术处理并用结果(作为字符串)替换自身。

因此,如果您输入“10 *”,则 $((${a[@]} $n)) 第一次处理 10 * 1,因此 printf "%+10s\n" $((${a[@]} $n)) 输出带有尾随换行符的“10”。然后循环在每次迭代时用下一个数字替换 1,最多为 15。这也允许使用其他运算符,例如用于模数的 %,但如果给出无效的值,则会崩溃。

如果你想要错误检查 -

while [[ ! "${a[*]}" =~ ^[0-9][0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a, integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+10s\n" $((${a[@]} $n)); done

如果你想要浮点数学,试试bc

while [[ ! "${a[*]}" =~ ^[0-9]+.?[0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a, integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+15s\n" $(bc -l  <<< "scale=3;${a[@]} $n"); done

就个人而言,我会将输入放在命令行上。不太模糊,尽管它可能需要引用 * 运算符,具体取决于您的运行方式和目录中的内容。

#!/bin/bash

me=${0##*/}
use="
  use: $me {number} {operator} [iterations] [scale]

  Numbers may include one decimal point.
  Operators must be one of: + - * / **

"
while getopts "n:o:i:s:" arg
do case $arg in
   n) n="$OPTARG" ;;
   o) o="$OPTARG" ;;
   i) i="$OPTARG" ;;
   s) s="$OPTARG" ;;
   *) printf "%s\n" "Invalid argument '$arg' $use";
      exit 1;;
   esac
done

[[ -n "$n" && -n "$o"             ]] || { echo                                                     "$use"; exit 1; }
[[ "$n"       =~ ^[0-9]+.?[0-9]*$ ]] || { printf "%s\n" "Invalid number   '$n'                      $use"; exit 1; }
[[ "$o"       =~ ^([*/^+-]|\*\*)$ ]] || { printf "%s\n" "Invalid operator '$o'                      $use"; exit 1; }
[[ "${i:=15}" =~ ^[0-9]+.?[0-9.]$ ]] || { printf "%s\n" "Invalid number   '$i'                      $use"; exit 1; }
[[ "${s:=3}"  =~ ^[0-9]+$         ]] || { printf "%s\n" "Invalid scale    '$s' (must be an integer) $use"; exit 1; }

c=1
while ((c < i))
do printf "%+15s\n" $(bc -l <<< "scale=$s; $n $o $c")
   ((c++))
done