【问题标题】:How do I rewrite a bash 'while' loop as a 'for' loop?如何将 bash 'while' 循环重写为 'for' 循环?
【发布时间】:2014-09-03 04:24:27
【问题描述】:

这是我的 bash 脚本代码,所以我想知道如何使用“for”循环而不是“while”循环来重写下面的 Bash 脚本。

  #!/bin/bash
    if [ $# -gt 0 ]; then                
           a=0;                
           if [ -f RandNos ]; then
               rm RandNos;
           fi

           while [ $a -lt $1 ]
           do
               a='expr $a + 1';
               myrand=$RANDOM;

              if [ "$2" "1"]; then
                  echo "No. $a ==> $myrand";
              fi

              echo $myrand>>RandNos
           done                
    else 
        echo "please use with an argument..."
    fi

谢谢。

【问题讨论】:

标签: bash for-loop while-loop


【解决方案1】:

简而言之:对于基于计数器的循环,请使用for 循环的类C 形式

    for (( a = 0; a < $1; a++ )); do
        # ... use $a
    done

(这取代了while [ $a -lt $1 ]; do a='expr $a + 1' ...; done。)

有关适用于(( ... )) 的规则的更多信息,请参见下文。


至于你的代码的其余部分

  • 条件[ "$2" "1"] 已损坏:它缺少] 之前的必填空格
    • 修复该问题后,它仅在 $2 扩展为一元测试运算符(例如 -n)时才有效。
    • 也许您的意思是if [[ -z $myrand ]]; then,以检查$RANDOM 是否导致非空字符串?
  • a='expr $a + 1' - for 循环不再需要它 - 实际上不会调用 expr,因为您使用的是 单引号 - 你' d 需要 反引号 (`) 代替,或者最好是现代的等价物:$(expr $a + 1)。但是,通过算术评估,这可以简化为 (( ++a ))

  • [ ... ] 条件在 bash 中工作,但它们是为 POSIX 兼容性而提供的 - 使用[[ ... ]] 作为 bash 特定的替代方案,它更健壮、具有更多功能并且速度更快。

  • bash 语句只需要以; 结束,如果你将multiple放在一行

    • 请注意,bash 将do ...then ... 视为单独的语句,因此您经常会看到if ...; thenfor ...; do
  • 一般来说,我鼓励您http://shellcheck.net 上对您的 shell 代码进行语法检查 - 这是检测语法问题的好工具。

请注意与bash 中的其他地方相比,(( ... )) 中应用的规则有何不同:

  • 变量赋值中= 周围的空格允许
  • 允许引用不带 $ 前缀 (a++) 的变量。
  • &lt; 执行 numerical 比较(而在 [[ ... ]] 内部它是 lexical)-即,它更自然地等效于 -lt[ ... ][[ ... ]] 内部。
  • 支持其他几种数学甚至位运算符
  • ...

当 bash 在算术上下文中运行时,所有这些不同的规则都适用,这适用于(( ... ))$(( ... ))、数组下标和其他情况。
对于所有规则,运行man bash 并阅读ARITHMETIC EVALUATION 部分。

【讨论】:

    【解决方案2】:

    简单地用for 循环重写它会导致:

    #!/bin/bash
    if [ $# -gt 0 ]; then
       if [ -f RandNos ]; then
          rm RandNos;
       fi
       lim=$(expr $1 - 1)
       as=$(seq 0 $lim)
       for a in $as
       do
          a='expr $a + 1';
          myrand=$RANDOM;
          if [ "$2" "1"]; then  # <- Caveat: conditional is BROKEN
             echo "No. $a ==> $myrand";
          fi
          echo $myrand>>RandNos
       done
    else 
       echo "please use with an argument..."
    fi
    

    但无论如何,脚本有几处错误。就像最后一个 if 声明一样。

    【讨论】:

      【解决方案3】:
      if [ $# -lt 1 ];then
          echo "First argument must be number".
          exit 1;
      fi
      
      for a in `seq $1`
      do
           ...
      done
      

      【讨论】:

        【解决方案4】:

        有几点可以改进:

        #!/bin/bash
        if (( $# )); then                              # anything but 0 is true
           rm -f RandNos                            # remove if existing, otherwise fail silently
           for ((a=0; a<$1; a++)); do
              myrand=$RANDOM
        
        #  what is the intention here?
              (( $2 > 1 )) && echo "No. $a ==> $myrand"
              echo "$myrand" >> RandNos
           done
        else
           echo "please use with an argument..."
        fi
        

        不确定您使用 [ "$2" "1" ] 表达式的意图是什么。这可能不是我用它做的。

        for ((a=1; a<=$1; a++)); do
        

        可能会更好地反映您的预期逻辑,因为您仅在增加 $a 后才将其用于输出。正如@mklement0 指出和纠正的那样

        【讨论】:

        • ((a=0; a&lt;$1; a++))((a=0; a&lt;$1; ++a)) 相同:在循环内部,$a0 开头,$a 仅递增 after 每次迭代 - 换句话说:使用前增量还是后增量都没有关系。如果您真的想从1 开始,请使用((a=1; a&lt;=$1; a++))
        【解决方案5】:

        !/bin/bash

        if [ $# -gt 0 ]; then
        
        a=0;
            if [ -f RandNos ]; then
                rm RandNos;
            fi
            for (( i=$a; i<$1; i++ ))
        
            do
           
            myrand=$RANDOM;
            if [ "$2" = "1" ]; then
                echo "No. $a ==> $myrand";
            fi
            echo $myrand >> RandNos
            done
        else
            echo "please use with an argument..."
        fi
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-24
          • 2018-03-19
          • 1970-01-01
          • 2021-12-30
          • 1970-01-01
          • 2014-03-15
          • 2014-08-06
          相关资源
          最近更新 更多