Shell学习笔记 03 流程控制

Posted by Huper on December 24, 2017

Shell里的流程控制和函数种类还挺多的,直接开始逐个说明:

if elif else fi

先看里例子(这里我用的是Cygwin)的命令行:

a=10
b=11
if [ $a == $b ]
then
        echo "a=b"
elif [ $a -gt $b ]
then
        echo "a>b"
else
        echo "a<b"
fi
--------------------------------------------
C:\Users\Huper>bash ./shelltest.sh
a<b

可以看到,语法要求一如既往的严格,条件必须使用[]括起来,并且左右都要留白。每个条件之后都要使用then关键字,elif关键字也与其他编程语言不太一样,并且最后必须使用fi关键字结束条件分支。

for循环

Shell的for循环语法和python很像,使用方式也比较多,先来看个例子:

for item in 1 2 3 4 5       #for in; do 
do
        echo "temp item is $item"
done
----------------------------------------------
C:\Users\Huper>bash shelltest.sh
temp item is 1
temp item is 2
temp item is 3
temp item is 4
temp item is 5

for循环必须使用严格的for-in-do-done组合,也可以把他们写在同一行,但是必须用分号把关键字隔开:

Huper@DESKTOP-AT9MCJI  ~
$ num=(1 2 3)
Huper@DESKTOP-AT9MCJI  ~
$ for item in ${num[*]};do echo "temp item is $item";done
temp item is 1
temp item is 2
temp item is 3

不过最好还是严格换行来写,比较规矩。for循环还可以搭配出很多用法,比如:

# 打印指定目录下所有问价(*表示当前目录)
$ for FILE in *
> do
> echo $FILE
> done
# 按关键字打印某个文件所有内容
$ info=`cat shelltest.sh`
Huper@DESKTOP-AT9MCJI  ~
$ for line in $info
> do
> echo $line
> done
# 还有这些操作
$ for i in $(seq 0 4);do echo $i;done
$ for i in `seq 0 4`;do echo $i;done
$ for i in {0..4};do echo $i;done

while循环

使用方式类似for循环,还是直接看例子:

$ while [ $c -lt 3 ]; do echo "$c"; c=`expr $c + 1`; done
0
1
2
# 上述写法等价于
$ while [ $c -lt 3 ]
> do
> echo $c
> let "c++"
> done
# 并且等价于
$ while(( c<3 ))
> do
>     echo $c
>     let "c++"
> done

第三种写法里的(())POSIX标准的扩展计算,两边不留白也可以。用它可以实现C语言里的计算操作(并不支持浮点操作),比如:

$ for ((i=0;i<4;i++));do echo $i;done

实时上,Shell的关键字里还有一个[[]],它允许我们不对某些字符转义(但是两边必须留白)来使用判断语句,它和[]都被称为测试表达式:

----------------------------
# 以下写法等效
if [ $a -ne 1 -a $a != 2 ]
if [ $a -ne 1] && [ $a != 2 ]
if [[ $a != 1 && $a != 2 ]]
----------------------------
Huper@Huper:~$ [ 1 < 2 ]
-bash: 2: No such file or directory
Huper@Huper:~$ [[ 1 < 2 ]] && echo True || echo False
True

until循环

Shell里还有类似Pascal的until,用法如下:

# 以下写法等效
$ until ((c>4));do echo $c;let "c++";done
$ until ((c>4));do echo $c;c=`expr $c + 1`;done
$ until ((c>4));do echo $c;((c++));done
$ until [[ $c > 4 ]];do echo $c;((c++));done
# 这里中间不留白也可以,仅限于引用,比如[[ 1>2 ]]这种写法就不行,因为1不是引用。
$ until [[ $c>4 ]];do echo $c;((c++));done
$ until [ $c -gt 4 ];do echo $c;((c++));done

case语句

似乎脚本语言里习惯了将case语句成为模式匹配,直接来看下用法:

$ read num
10
Huper@DESKTOP-AT9MCJI  ~
$ case $num in
> 1) echo "$num"
> ;;
> 2) echo "$num"
> ;;
> 3|4|5) echo "$num"
> ;;
> *) echo "others"
> ;;
> esac
others
# 上述写法等价于
Huper@DESKTOP-AT9MCJI  ~
$ case $num in 1) echo "$num"; ;; 2) echo "$num"; ;; *) echo "others"; ;; esac

需要注意的东西比较懂,首先说下read命令,负责从命令行接受一个参数。Shell里的模式使用value)的形式表示的,并且,default值是*),这里可以使用|合并多个模式。与if一样,结束标志是把开始标志倒过来。注意这里模式划分标志是;;,它不等于break。因为Shell里的break只用于跳出循环。

break和continue

这个用法及意义和其他语言完全一样,就不讲了。