如何将bash'while'循环重写为'for'循环?

时间:2014-07-12 19:16:07

标签: bash for-loop while-loop

这是我的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

感谢。

5 个答案:

答案 0 :(得分:4)

缺点:对于基于计数器的循环,请使用{strong> C-like形式的for循环:

    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,因为您正在使用单引号 - 您需要反引号(`),或者最好是现代等价物:$(expr $a + 1)。但是,通过算术评估,可以将其简化为(( ++a ))

  • [ ... ]条件在bash中有效,但它们是为POSIX兼容性提供的 - 使用[[ ... ]]作为特定于bash的替代方案,它更强大,有更多功能功能更快

  • 如果您将多个放在单行
  • bash 语句只需要以;终止

    • 请注意,bash会考虑do ...then ...个单独的陈述,因此您经常会看到if ...; thenfor ...; do
  • 一般情况下,我建议您在http://shellcheck.net 语法检查您的shell代码 - 它是检测语法问题的绝佳工具。

请注意(( ... )) 内的不同规则与bash中的其他地方相比如何适用:

  • 变量分配中=周围的空格允许
  • 引用不带$前缀(a++)的变量允许
  • <执行数字比较(而在[[ ... ]]里面词汇)-ie,它就越多自然相当于-lt[ ... ]内的[[ ... ]]
  • 支持其他几个数学运算符甚至逐位运算符
  • ...

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

答案 1 :(得分:1)

只需使用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声明一样。

答案 2 :(得分:1)

可以改进几件事:

#!/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指出并更正

答案 3 :(得分:1)

if [ $# -lt 1 ];then
    echo "First argument must be number".
    exit 1;
fi

for a in `seq $1`
do
     ...
done

答案 4 :(得分:0)

!/斌/庆典

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