第四章 Shell流程控制

流程控制是改变程序运行顺序的指令。

4.1 if语句

4.1.1 单分支

if 条件表达式; then
命令
fi

示例:

#!/bin/bash
N=10
if [ $N -gt 5 ]; then
echo yes
fi
# bash test.sh
yes

4.1.2 双分支

if 条件表达式; then
命令
else
命令
fi

示例:

#!/bin/bash
N=10
if [ $N -lt 5 ]; then
echo yes
else
echo no
fi
# bash test.sh
no

4.1.3 多分支

if 条件表达式; then
命令
elif 条件表达式; then
命令
else
命令
fi

示例:

#!/bin/bash
N=10
if [ $N -gt 5 ]; then
echo "gt 5"
elif [ $N -gt 6 ]; then
echo "gt 6"
else
echo no
fi

如果第一个条件符合就不再向下匹配。

4.2 for语句

for 变量名 in 取值列表; do
命令
done

示例:

#!/bin/bash
for i in {1..3}; do
echo $i
done
# bash test.sh
1
2
3

for的语法也可以这么写:

#!/bin/bash
for i in $@; {
echo $i
}
# bash test.sh 1 2 3
1
2
3

默认for循环的取值列表是以空白符分隔,也就是第一章讲系统变量里的$IFS:

#!/bin/bash
for i in 12 34; do
echo $i
done
# bash test.sh
12
34

如果想指定分隔符,可以重新赋值$FS变量:

#!/bin/bash
OLD_IFS=$IFS
IFS=":"
STR="12:34:45"
for i in $STR; do
echo $i
done
IFS=$OLD_IFS   # 恢复默认值
# bash a.sh
12
34
45

for循环还有一种C语言风格的语法:

#!/bin/bash
for ((i=1;i<=5;i++)); do
echo $i
done

博客地址:http://lizhenliang.blog.51cto.com

QQ群:323779636(Shell/Python运维开发群)

4.3 while语句

while 条件表达式; do
命令
done

示例1:

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
let N++
echo $N
done
# bash test.sh
1
2
3
4
5

当条件表达式为true时,终止循环。

示例2:条件表达式为false,将会产生死循环

#!/bin/bash
while [ 1 -eq 1 ]; do
echo "yes"
done

也可以条件表达式直接用true:

#!/bin/bash
while true; do
echo "yes"
done

还可以条件表达式用冒号,冒号在Shell中的意思是不做任何操作。但状态是0,因此为true:

#!/bin/bash
while :; do
echo "yes"
done

示例3:在死循环中,满足条件终止循环

#!/bin/bash
N=0
while true; do
let N++
if [ $N -eq 5 ]; then
break
fi
echo $N
done
# bash test.sh
1
2
3
4

里面用了if判断,并用了break语句,它是跳出循环。与其关联的还有一个continue语句,它是跳出本次循环。

示例4:举例子说明continue用法

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
let N++
if [ $N -eq 3 ]; then
continue
fi
echo $N
done
# bash test.sh
1
2
4
5

当变量N等于3时,continue跳过了当前循环,没有执行下面的echo。

注意:continue与break语句只能循环语句中使用。

示例5:逐行处理文本

文本内容:

# cat a.txt
a b c
1 2 3
x y z

要想使用while循环逐行读取a.txt文件,有三种方式:

方式1:
#!/bin/bash
cat ./a.txt | while read LINE; do
echo $LINE
done
方式2:
#!/bin/bash
while read LINE; do
echo $LINE
done < ./a.txt
方式3:
#!/bin/bash
exec < ./a.txt  # 读取文件作为标准输出
while read LINE; do
echo $LINE
done

与while关联的还有一个until语句,它与while不同之处在于,是当条件表达式为false时才循环,实际使用中比较少,这里不再讲解。

4.4 case语句

case语句一般用于选择性来执行对应部分块命令。

case 模式名 in
模式1)
命令
;;
模式2)
命令
;;
*)
不符合以上模式执行的命令
esac

每个模式必须以右括号结束,命令结尾以双分号结束。

示例:根据位置参数匹配不同的模式

#!/bin/bash
case $1 in
start)
echo "start."
;;
stop)
echo "stop."
;;
restart)
echo "restart."
;;
*)
echo "Usage: $0 {start|stop|restart}"
esac

# bash test.sh
Usage: test.sh {start|stop|restart}
# bash test.sh start
start.
# bash test.sh stop
stop.
# bash test.sh restart
restart.

上面例子是不是有点眼熟,在Linux下有一部分服务启动脚本都是这么写的。

模式也支持正则,匹配哪个模式就执行那个:

#!/bin/bash
case $1 in
[0-9])
echo "match number."
;;
[a-z])
echo "match letter."
;;
-h|--help)
echo "help"
*)
echo "Input error!"
exit
esac
# bash test.sh 1
match number.
# bash test.sh a
match letter.
# bash test.sh -h
help
# bash test.sh --help
help

模式支持的正则有:*、?、[ ]、[.-.]、|。后面有章节单独讲解Shell正则表达式。

4.5 select语句

select是一个类似于for循环的语句。

select 变量 in 选项1 选项2; do
break
done

示例:

#!/bin/bash
select mysql_version in 5.1 5.6; do
echo $mysql_version
done
# bash test.sh
1) 5.1
2) 5.6
#? 1
5.1
#? 2
5.6

用户输入编号会直接赋值给变量mysql_version。作为菜单用的话,循环第二次后就不再显示菜单了,并不能满足需求。

在外面加个死循环,每次执行一次select就break一次,这样就能每次显示菜单了:

#!/bin/bash
while true; do
select mysql_version in 5.1 5.6; do
echo $mysql_version
break
done
done
# bash test.sh
1) 5.1
2) 5.6
#? 1
5.1
1) 5.1
2) 5.6
#? 2
5.6
1) 5.1
2) 5.6

如果再判断对用户输入的编号执行相应的命令,如果用if语句多分支的话要复杂许多,用case语句就简单多了。

#!/bin/bash
PS3="Select a number: "
while true; do
select mysql_version in 5.1 5.6 quit; do
case $mysql_version in
5.1)
echo "mysql 5.1"
break
;;
5.6)
echo "mysql 5.6"
break
;;
quit)
exit
;;
*)
echo "Input error, Please enter again!"
break
esac
done
done
# bash test.sh
1) 5.1
2) 5.6
3) quit
Select a number: 1
mysql 5.1
1) 5.1
2) 5.6
3) quit
Select a number: 2
mysql 5.6
1) 5.1
2) 5.6
3) quit
Select a number: 3

如果不想用默认的提示符,可以通过重新赋值变量PS3来自定义。这下就比较完美了!

  • 版权声明: 本文源自互联网, 于2个月前,由整理发表,共 734字。
  • 原文链接:点此查看原文