shell流程控制

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

1. if语句

格式:if list; then list; [ elif list; then list; ] ... [ else list; ] fi

1.1 单分支

if 条件表达式; then 
    命令 
fi

示例:

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

1.2 双分支

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

示例1:

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

示例2:判断crond进程是否运行

#!/bin/bash 
NAME=crond 
NUM=$(ps -ef |grep $NAME |grep -vc grep) 
if [ $NUM -eq 1 ]; then 
     echo "$NAME running." 
else 
     echo "$NAME is not running!" 
fi 

示例3:检查主机是否存活

#!/bin/bash 
if ping -c 1 192.168.1.1 >/dev/null; then  
echo "OK." 
else  
echo "NO!" 
fi 

if语句可以直接对命令状态进行判断,就省去了获取$?这一步!

1.3 多分支

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

当不确定条件符合哪一个时,就可以把已知条件判断写出来,做相应的处理。

示例1:

#!/bin/bash 
N=$1 
if [ $N -eq 3 ]; then 
    echo "eq 3" 
elif [ $N -eq 5 ]; then 
    echo "eq 5" 
elif [ $N -eq 8 ]; then 
    echo "eq 8" 
else 
    echo "no" 
fi 

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

示例2:根据Linux不同发行版使用不同的命令安装软件

#!/bin/bash 
if [ -e /etc/redhat-release ]; then 
    yum install wget -y 
elif [ $(cat /etc/issue |cut -d' ' -f1) == "Ubuntu" ]; then 
    apt-get install wget -y 
else 
    Operating system does not support. 
    exit 
fi 

2. for语句

格式:for name [ [ in [ word ... ] ] ; ] do list ; done

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

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

#!/bin/bash 
OLD_IFS=$IFS 
IFS=":" 
for i in $(head -1 /etc/passwd); do 
    echo $i 
done 
IFS=$OLD_IFS   # 恢复默认值 
# bash test.sh    
root 
x 
0 
0 
root 
/root 
/bin/bash 

for循环还有一种C语言风格的语法,常用于计数、打印数字序列:

for (( expr1 ; expr2 ; expr3 )) ; do list ; done

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

示例1:检查多个主机是否存活

#!/bin/bash 
for ip in 192.168.1.{1..254}; do 
    if ping -c 1 $ip >/dev/null; then 
        echo "$ip OK." 
    else 
        echo "$ip NO!" 
    fi 
done

示例2:检查多个域名是否可以访问

#!/bin/bash 
URL="www.baidu.com www.sina.com www.jd.com" 
for url in $URL; do 
    HTTP_CODE=$(curl -o /dev/null -s -w %{http_code} http://$url) 
    if [ $HTTP_CODE -eq 200 -o $HTTP_CODE -eq 301 ]; then 
        echo "$url OK." 
    else 
        echo "$url NO!" 
    fi 
done 

3. while语句

格式:while list; do list; done

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

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

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

#!/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 

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

4. break和continue语句

break是终止循环。 continue是跳出当前循环。

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

#!/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语句,它是 跳出本次循环。

示例2:举例子说明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. case语句

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

格式:case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

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正则表达式。

6. select语句

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

格式:select name [ in word ] ; do list ; done

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来自定义。这下就比较完美了!

你可能感兴趣的:(linux,运维,服务器)