shell 脚本编程之循环语句

for 循环

带列表的 for 循环
for VAR in list
do
    command
done

for 循环会遍历列表的每一项,逐项赋给变量 VAR,然后对变量 VAR 进行操作。shell 的列表很随意,几个项之间用空格隔开就是一个列表,如 for var in a b c 遍历的就是列表 {a b c},for var in 1 2 3 遍历的就是列表 {1 2 3}。
关于数字列表可以使用 {start..end} 来表示一个顺序列表,也可以使用 seq 命令来生成,语法是 seq start step end,step 可省略。

#learn_loop_for.sh
#!/bin/bash
for fruit in apple banana pear orange
do
    echo $fruit is my favoriate
done

for i in {1..5}
do
    echo -n "$i " 
done

echo

for i in $(seq 1 2 10)
do
    echo -n "$i "
done

执行结果

apple is my favoriate
banana is my favoriate
pear is my favoriate
orange is my favoriate
1 2 3 4 5
1 3 5 7 9
不带列表的 for 循环
for VAR
do
    command
done

不带列表的 for 循环就是省略了后面的列表,但其实还是有列表的,这个列表就是脚本的参数列表。也就是说上面的结构等价于

for VAR in $@ #或 $*
do
    command
done
类 C 的 for 循环
for ((expression1;expression2;expression3))
do
    command
done

这种 for 循环与 c 语言特别相似,不同的是 for 后面要用两对括号。

#!/bin/bash
for((i=1,j=100;i<5;i++,j--))
do
    echo "$i $j"
done

执行结果

1 100
2 99
3 98
4 97

while 循环

while expression
do
    command
done

while 循环当 expression 为真时会一直执行循环体,直到 expression 为假时跳出循环。

until 循环

until expression
do
    command
done

until 循环和 while 循环刚好相反,当 expression 为真时立即跳出循环,否则一直执行循环体直到条件为真。

select 循环

select VAR in list
do
    command
done

select 列表的结构和 for 有点相似,也是遍历一个列表。select 循环是一种菜单扩展循环,它会把列表的所有项取出来并用序号 1,2,3 来标明输出,然后等待用户选择序号。select 循环不会自动跳出循环,必须使用 break 或 exit 等命令退出。

#!/bin/bash
echo please select a day
days="Mon Tue Wed Thr Fri Sat Sun"
select day in $days
do
    case $day in
        Mon) echo Today is Monday ;;
        Tue) echo Today is Tuesday ;;
        Wed) echo Today is Wednesday ;;
        Thr) echo Today is Thursday ;;
        Fri) echo Today is Friday ;;
        Sat|Sun) echo Today is rest day ;;
        *) echo unknown select and now exit && break ;;
    esac
done

执行结果

please select a day
1) Mon
2) Tue
3) Wed
4) Thr
5) Fri
6) Sat
7) Sun
#? 1
Today is Monday
#? 6
Today is rest day
#?
1) Mon
2) Tue
3) Wed
4) Thr
5) Fri
6) Sat
7) Sun
#? 5
Today is Friday
#? 0
unknown select and now exit

select 循环将列表项按 1-7 的编号打印出来,然后等待用户选择,如果用户没选择任何一个序号就直接按回车,shell 将再次打印出列表项。当输入 1-7 之外的内容,case 判断将进入 default 分支,break 语句用于跳出循环,注意 case 语句并不需要 break 语句,这和 c 语言很不一样。

break && continue

break 和 continue 的意义和 c 语言一样,break 用于结束整个循环,continue 用于跳过本次循环。但 shell 的 break 和 continue 有一个很强大的地方就是可以带上一个数字,表示作用于哪一层循环。默认不带数字表示作用于 break 或 continue 所在的那一层循环。break 2 表示直接跳出 break 外面的那一层循环。
下面实现一个求 100 以内所有素数的脚本

#!/bin/bash
for((i=2;i<=100;i++))
do
    j=2
    for((;j<i;j++))
    do
        if ! (($i%$j)); then
            break
        fi
    done
    if (($j==$i)); then
        echo -n "$i "
    fi
done

执行结果

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

这是 c 语言的一般做法,内层循环判断 i 能否被 2-i 之间的数整除,如果找到能整除的数,则跳出内层循环;在内层循环之后判断 j 的值,如果小于 i 说明内层循环提前被 break 掉,也就是有可以整除的数,因此 i 不是素数。但在 shell 中还有另一种写法

#!/bin/bash
for((i=2;i<=100;i++))
do
    for((j=2;j<i;j++))
    do
        if (($i%$j==0)); then
            continue 2
        fi
    done
    echo -n "$i "
done

这个脚本的关键在 continue 2 这个语句,当内层循环找到可以整除的数时,不是 break 掉内层循环,而是跳过外层循环,所以内层循环剩下的遍历和内层循环之后的操作都会被跳过。

”死循环“

for((;1;)
do
    command
done

判定条件不一定是 1,只要是非 0 的数字都表示真。

while ((1))
do
    command
done
while true
do
    command
done
while :
do
    command
done

同样,第一种写法的判定条件不一定要是 1,只要是非 0 的数字都表示真。

until ((0))
do
    command
done
until false
do
    command
done

第一种写法的判定条件必须是 0,其它非 0 的数字都表示真,会马上结束循环。

嵌套循环

嵌套循环其实没什么好讲的,前面已经用过了。这里再提一下,每种循环都可以嵌套,不同的循环结构也可以相互嵌套;下面用两层循环实现一个九九乘法表

#!/bin/bash
i=1
while (($i<10))
do
    for j in `seq 1 $i`
    do
        echo -n "$i*$j=$[$i*$j] "
    done
    echo
    let "i++"
done

这个脚本外层循环使用 while 结构,内层循环使用 for 列表结构,这其实不是一种好的写法,只是为了测试不同的循环结构可以相互嵌套。一个好的写法如下

#!/bin/bash
for((i=1;i<=9;i++))
do
    for((j=1;j<=i;j++))
    do
        echo -n "$i*$j=$[$i*$j] "
    done
    echo
done

执行结果

1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

“真” & “假”

条件语句和循环语句经常需要判断条件的真假,这里再总结一下 shell 中的“真”和“假”。

  • 第一种,使用字符串 true 表示真,false 表示假
    这种方式直接使用字符串直接量来表示,只能是 true 或者 false 这两个直接量,如果使用其它字符串,命令将报错
#!/bin/bash
if true; then
    echo doing
fi
if "true"; then
    echo doing
fi
if "other"; then
    echo doing
fi

执行结果

doing
doing
./test.sh: line 8: other: command not found
  • 第二种,使用 (()) 括起来的判定表达式,这个表达式可以是比较表达式,也可以是一个数字,数字 0 表示假,其它数字表示真。这种用两对括号括起来的表达式,其实就跟 c 语言很像了。
#!/bin/bash
if ((5>3 && 5>1)); then
    echo go
fi
if ((1)); then
    echo go
fi
if ((0)); then
    echo go
fi

执行结果

go
go

注意到 (()) 里面的表达式直接用 >,< 等符号来作比较,这点要与测试区别开来。总的来说,就是这种 (()) 的写法与高级语言更加相似。

  • 第三种,使用测试。测试的返回值为 0 时表示真,非 0 时表示假,这个返回值 0 与 ((0)) 的意义是不一样的。
if [[ 5 -gt 3 ]]; then
    echo go
fi

等价于

[[ 5 -gt 3 ]]
if (($?==0)); then
    echo go
fi
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值