Linux下Shell流程控制

Shell流程控制

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

1、if语句

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

1)单分支
if 条件表达式; then
  命令
fi

示例:
#!/bin/bash

N=10
if [ $N -gt 5 ]; then
  echo yes
fi

[root@ chenc01 ~]# bash test.sh
yes
2)双分支
if 条件表达式; then
  命令
else
  命令
fi

示例1:
#!/bin/bash

N=10
if [ $N -lt 5 ]; then
  echo yes
else
  echo no
fi

[root@ chenc01 ~]# 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语句可以直接对命令状态进行判断,就省去了获取$?这一步!
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

[root@ chenc01 ~]# bash test.sh
1
2
3

for的语法也可以这么写:

#!/bin/bash

for i in "$@"; {   # $@是将位置参数作为单个来处理
  echo $i
}

[root@ chenc01 ~]# bash test.sh 1 2 3
1
2
3

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

#!/bin/bash

for i in 12 34; do
  echo $i
done

[root@ chenc01 ~]# 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  # 恢复默认值

[root@ chenc01 ~]# 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

[root@ chenc01 ~]# 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
示例3:逐行处理文本

文本内容:

[root@ chenc01 ~]# 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、break和continue语句

break是终止循环。

continue是跳出当前循环。

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

#!/bin/bash

N=0
while true; do
  let N++
  if [ $N -eq 5 ]; then
     break
  fi
  echo $N
done

[root@ chenc01 ~]# 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

[root@ chenc01 ~]# 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

[root@ chenc01 ~]# 每个模式必须以右括号结束,命令结尾以双分号结束。

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

#!/bin/bash

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

[root@ chenc01 ~]# bash test.sh
Usage: test.sh {start|stop|restart}
[root@ chenc01 ~]# bash test.sh start
start.
[root@ chenc01 ~]# bash test.sh stop
stop.
[root@ chenc01 ~]# 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 

[root@ chenc01 ~]# bash test.sh 1
match number.
[root@ chenc01 ~]# bash test.sh a
match letter.
[root@ chenc01 ~]# bash test.sh -h
help
[root@ chenc01 ~]# 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

[root@ chenc01 ~]# bash test.sh
1) 5.1
2) 5.6
[root@ chenc01 ~]#? 1
5.1
[root@ chenc01 ~]#? 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

[root@ chenc01 ~]# bash test.sh
1) 5.1
2) 5.6
[root@ chenc01 ~]#? 1
5.1
1) 5.1
2) 5.6
[root@ chenc01 ~]#? 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

[root@ chenc01 ~]# 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来自定义。这下就比较完美了!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值