• Shell 循环语句、条件判断的使用方法及其相关示例

bash脚本条件判断语句使用;

  •  test语句的使用说明

  •  if判断语句的使用

  •  case判断语句的应用

   条件测试:test

       说明介绍:shell中的test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

       test的使用语法 : test EXPRESSION 或者  [ EXPRESSION ];` EXPRESSION `

   整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;

$A -gt $B:是否大于;是则为“真”,否则为“假”;

$A -ge $B: 是否大于等于;

$A -lt $B:是否小于;

$A -le $B: 是否小于等于;

$A -eq $B: 是否等于;

$A -ne $B:是否不等于;

   字符串测试:ASCII数值越大,字符比较时其值越大;

"$A" > "$B":是否大于;

"$A" < "$B":是否小于;

"$A" == "$B":是否等于;

"$A" != "$B":是否不等于;

-z "$A":是否为空;空则为“真”,否则为“假”

-n "$A":是否不空;不空则“真”,空则为“假”

                        PS :应该使用` EXPRESSION `

   文件测试:测试文件的存在性以及属性;

-e $file: 是否存在;存在则为“真”,否则为“假”;

-a $file: 同上;

-f $file:文件是否存在且为普通文件;

-d $file:文件是否存在且为目录;

-h $file:是否存在且为符号链接文件;

-L $file: 同上

-b $file:是否存在且为块设备文件;

-c $file:是否存在且为字符设备文件;

-S $file:是否存在且为套接字文件;

-p $file: 是否存在且为管道文件;

-r $file: 当前用户对文件是否拥有读权限;

-w $file:当前用户对文件是否拥有写权限;

-x $file:当前用户对文件是否拥有执行权限;

-u $file:文件是否拥有SUID权限;

-g $file:文件是否拥有SGID权限;

-k $file:文件是否拥有sticky权限;

-O $file: 当前用户是否为指定文件的属主;

-G $file: 当前用户是否为指定文件的属组;

一般这些都和if等判断结合使

If 判断语句:

       语法格式:if/then, case

 if CONDITION; then

 if-true-分支

 fi

                 if CONDITION; then

if-true-分支

 else

if-false-分支

  fi

                 ! CONDITION: 取反

例子:

   写一个脚本;如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;

#!/bin/bash#filename="/tmp/a/b/c/testdir"if [ -e $filename ]; thenecho "$filename exists."file $filenameelse   mkdir -p $filenamefi

      

  脚本参数(位置参数变量):

# ./script.sh /etc/fstab /etc/grub2.cfg

     $0          $1          $2

位置参数变量:$1, $2, ...${10}...

${10}

                 特殊变量:

$?: 命令的状态结果;

$#: 传递给脚本或函数的参数的个数;

$*和$@: 引用传递给脚本或函数的参数列表;

                 shift [n]:轮替  //执行一次$2会变成$1

与用户交互的read命令:

read [options] VAR...

-p "PROMPT"  描述信息

-t timeout    如果没有键盘输入等待时间自动结束

示例:

#!/bin/bash#read -p "请输入用户名称: " -t 5 usernameif [ -z "$username" ]; then    username="myuser"fiif id $username &> /dev/null; thenecho "$username exists."elseuseradd $usernamefi

命令的引用例子:

两种方法:  `COMMAND`, $(COMMAND)  引用命令的执行结果;

(1) ls `which cat`

(2) lines=$(wc -l /etc/fstab | cut -d' ' -f1)

#!/bin/bash#if [ -f $1 ]; then    lines=$(wc -l $1 | cut -d' ' -f1)    echo "$1 has $lines lines."    else    echo "$1 not exists or not a file."fi

练习:写一个脚本,完成如下功能;

      判断给定的两个数值,孰大孰小;

      给定数值的方法:脚本参数,命令交互;

#!/bin/bash#read -p "请输入两个数字: " -t 10 num1 num2if [ -z "$num1" ]; then    echo "请输入两个数字."    exit 1fiif [ -z "$num2" ]; then    echo "请给第二个数."     exit 1fiif [ $num1 -ge $num2 ]; then    echo "Max: $num1, Min: $num2."elseecho "Max: $num2, Min: $num1."fi

循环语句:

for, while, until

循环:将循环体代码执行0、1或多次;

进入条件:进入循环的条件;

退出条件:循环终止的条件;

命令的语法:

for VARIABLE in LIST; do

循环体

done

LIST:是由一个或多个空格或换行符分隔开的字符串组成;把列表的每个字符串逐个赋值给VARIABLE表示的变量;

for username in user1 user2 user3; do

循环体

done

 进入条件:列表非空;

 退出条件:列表遍历结束;

例子:添加10个用户,user1-user10;

#!/bin/bash#for username in user1 user2 user3 user4 user5; doif id $username &> /dev/null; then    echo "$username exists."    else    useradd $username     echo "Add user $username finished."fidone

LIST的生成方法:

(1) 整数列表

(a) {start..end}

(b) $(seq [start `step` end)

(2) 直接给出列表

(3) glob

(4) 命令生成

示例:数值列表

#!/bin/bash#for i in {1..10}; doif id user$i &> /dev/null; then   echo "user$i exists."elseuseradd user$iecho "Add user user$i finished."fidone

 

示例:glob

#!/bin/bash#for filename in /var/log/*; dofile $filenamedone

示例:命令生成列表

#!/bin/bash#for username in $(cut -d: -f1 /etc/passwd); doecho "$username primary group: $(id -n -g $username)."done

算术运算:

+, -, *, /, %, **

(1) $[$A+$B]

(2) $(($A+$B))

(3) let VARIABLE=$A+$B

(4) VARIABLE=$(expr $A + $B)

示例:求100以内所以正整数之和;

#!/bin/bash#declare -i sum=0for i in {1..100}; do   sum=$[$sum+$i]doneecho $sum

练习:求100以内所有偶数之和;

使用至少三种方法实现;

#!/bin/bash#declare -i sum=0for i in $(seq 0 2 100); do    sum=$(($sum+$i))doneecho "Even sum: $sum."

#!/bin/bash#declare -i sum=0for i in {1..100}; do    if [ $[$i%2] -eq 0 ]; thensum=$[$sum+$i]    fidoneecho "Even sum: $sum."

增强型赋值:

+=

sum=$[$sum+$i]

let sum+=$i

-=, *=, /=, %=

let count=$[$count+1]   --> let count+=1 --> let count++

let count=$[$count-1] --> let count-=1 --> let count--

示例:显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;

#!/bin/bash#declare -i count=0for file in /etc/*; do    if [ -f $file ]; then let count++echo "$count $file"    fidoneecho "Total: $count files."

测试表达式:

整数测试:-gt, -lt, -ge, -le, -eq, -ne

字符串测试:==, >, <, !=, -z, -n, =~

注意:

(1) 字符串等会比较测试:[ "$hostname" == 'localhost'  ]

(2) 模式匹配测试:[[ "STRING" =~ PATTERN ]]

组合测试条件:

条件间逻辑运算:

与:多个条件要同时满足;

或:多个条件满足其一即可;

非:对指定的条件取反;

表达式组合:

与:` CONDITION1 -a CONDITION2 `

或:` CONDITION1 -o CONDITION2 `

非:[ ! CONDITION ]

命令组合:

与:COMMAND1 && COMMAND2  <-- [ EXPR1 ] && [ EXPR2 ] 

或:COMMAND1 || COMMAND2

非:! COMMAND

短路操作符:&&

false && true = false

false && false = false

true && false = true

true && true = true

if COMMAND1; then

COMMAND2

fi

短路操作符:||

true || true = true

true || false = true

false || true = true

false || false = false

if ! COMMAND1; then

COMMAND2

fi

COMMAND1 && COMMAND2 || COMMAND3

if COMMAND1; then

COMMAND2

else

COMMAND3

fi

示例:写一个脚本实现如下功能;

获取当前主机的主机名;

如果当前主机的主机名为空,或者为localhost,则将其修改为www.magedu.com

#!/bin/bash#hostname=$(hostname)if [ -z "$hostname" -o "$hostname" == "localhost" ]; then    hostname www.magedu.comfi

练习:写一个脚本,打印九九乘法表;

两个循环嵌套

#!/bin/bash#for j in {1..9}; dofor i in $(seq 1 $j); doecho -n -e "${i}X${j}=$[$i*$j]\t"doneecho done

多分支的if语句:

单分支语法:

if CONDITION; then

if-true-分支

fi

IF双分支语法:

if CONDITION; then

if-true-分支

else

if-false-分支

fi

IF多分支语法:

if CONDITION1; then

if-CONDITION1-true-分支

elif CONDTION2; then

if-CONDITIO2-true-分支

...

else

if-ALL-false-分支

fi

示例:通过脚本参数传递一个文件路径给脚本,判断其类型;

#!/bin/bash#if [ $# -lt 1 ]; then    echo "Usage: $0 
"    exit 1fiif [ -f $1 ]; then    echo "Rgular file."elif [ -d $1 ]; then    echo "Directory."elif [ -h $1 ]; then    echo "Symbolic link."elif [ -b $1 ]; then    echo "Block special."elif [ -c $1 ]; then    echo "Charactoer special."elif [ -S $1 ]; then    echo "Socket file."else    echo "file not exist or unknown type."fi

   典型案例示例:写一个脚本可接受四个参数,start: 创建文件/var/lock/subsys/SCRIPT_NAME  stop: 删除此文件     restart: 删除此文件并重新创建    status: 如果文件存在,显示为"running",否则,显示为"stopped" ### 想当于服务的启动 重启 关闭 状态 停止的脚本命令。  PS: basename命令:取得路径的基名;

   

#!/bin/bash#prog=$(basename $0)lockfile="/var/lock/subsys/$prog"#echo $lockfileif [ $# -lt 1 ]; thenecho "Usage: $prog start|stop|restart|status"exit 1fiif [ "$1" == "start" ]; thenif [ -f $lockfile ]; thenecho "$prog is started yet."elsetouch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."fielif [ "$1" == 'stop' ]; thenif [ -f $lockfile ]; thenrm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."elseecho "$prog is stopped yet."fielif [ "$1" == 'restart' ]; thenif [ -f $lockfile ]; thenrm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."elsetouch $lockfile && echo "$prog is stopped, Starting $prog ok...."fielif [ "$1" == 'status' ]; thenif [ -f $lockfile ]; thenecho "Running..."elseecho "Stopped..."fielseecho "Usage: $prog start|stop|restart|sttus"exit 1fi

 case语句

        介绍:简洁版多分支if语句,主要应用的场景:判断某变量的值是否为多种情形中的一种时使用;

        语法格式如下:

case $VARIABLE in 

PATTERN1)

分支1

;;

PATTERN2)

分支2

;;

PATTERN3)

分支3

;;

...

*)

分支n

;;

esac

PATTERN可使用glob模式的通配符:*: 任意长度的任意字符;?: 任意单个字符;[]: 指定范围内的任意单个字符;a|b: 多选1

语法示例:提示键入任意一个字符;判断其类型;

#!/bin/bash#read -p "Plz enter a character: " charcase $char in[a-z])echo "A character.";;[0-9])echo "A digit.";;*)echo "A special character.";;esac

典型案例示例:脚本可接受四个参数就是上面的if语句的可以简化成下面这样;

start: 创建文件/var/lock/subsys/SCRIPT_NAME stop: 删除此文件 restart: 删除此文件并重新创建  status: 如果文件存在,显示为"running",否则,显示为"stopped"

 

#!/bin/bash#prog=$(basename $0)lockfile="/var/lock/subsys/$prog"#echo $lockfileif [ $# -lt 1 ]; thenecho "Usage: $prog start|stop|restart|status"exit 1ficase $1 instart)if [ -f $lockfile ]; thenecho "$prog is started yet."elsetouch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."fi;;stop)if [ -f $lockfile ]; thenrm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."elseecho "$prog is stopped yet."fi;;restart)if [ -f $lockfile ]; thenrm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."elsetouch $lockfile && echo "$prog is stopped, Starting $prog ok...."fi;;status)if [ -f $lockfile ]; thenecho "Running..."elseecho "Stopped..."fi;;*)echo "Usage: $prog start|stop|restart|sttus"exit 1esac

流程控制的语句:

    循环语句:for, while, until

    while语句的循环:

    while CONDTION; do

    循环体

    done

    进入条件:当CONDITION为“真”;

    退出条件:当CONDITION为“假”;

    while CONDITION; do

          循环体

 控制变量的修正表达式

    done

示例:求100以内所有正整数之和;

#!/bin/bash

#

declare -i sum=0

declare -i i=1

while [ $i -le 100 ]; do

       let sum+=$i

       let i++

       done

echo "Sum: $sum."

示例:打印九九乘法表

#!/bin/bash#declare -i i=1declare -i j=1while [ $j -le 9 ]; dowhile [ $i -le $j ]; doecho -e -n "${i}X${j}=$[$i*$j]\t"let i++doneecholet i=1let j++done

示例:求100以内所有正整数之和

#!/bin/bash#declare -i sum=0declare -i i=1until [ $i -gt 100 ]; dolet sum+=$ilet i++doneecho "Sum: $sum."

循环控制:

continue [n]:提前结束本轮循环,而直接进入下一轮;

break [n]:提前结束循环;

while循环语法:

while CONDITION; do

.......

if CONDITION2; then

break [n]

fi

done

while CONDITION; do

......

if CONDITION2; then

continue [n]

fi

......

done

示例:求100以内所有偶数之和;

#!/bin/bash#declare -i sum=0declare -i i=0while [ $i -le 100 ]; dolet i++if [ $[$i%2] -eq 1 ]; thenecho "$i is a odd."continuefilet sum+=$idoneecho "Sum: $sum."

死循环体:

while true; do

循环体

if CONDTION; then

break

fi

done

until false; do

循环体

if CONDITION; then

break

fi

done

示例:每隔3秒钟查看当前系统上是否有名为“tooyang”的用户登录;如果某次查看tooyang登录了,则显示tooyang已经登录;如果未登录,就显示仍然未来,并显示这是已经是第多少次查看了;

#!/bin/bash#declare -i count=0username=$1if [ $# -lt 1 ]; then    echo "At lease one argument."    exit 1fiif ! id $username &> /dev/null; then    echo "No such user."    exit 2fiuntil who | grep "^$username" &> /dev/null; do    let count++    echo "$count $username is not login."    sleep 3doneecho "$username is logged on."

while循环的特殊用法:

遍历文件的每一行:

while read VARIABLE; do

循环体

done < /PATH/FROM/SOME_FILE

示例:找出UID为偶数的所有用户,显示其用户名和ID号;

#!/bin/bash#while read line; do    userid=$(echo $line | cut -d: -f3)    if [ $[$userid%2] -eq 0 ]; thenecho $line | cut -d: -f1,3    fidone < /etc/passwd

for循环的特殊用法:

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

循环体

done

expr1: 定义控制变量,并初始赋值;

expr2: 循环控制条件;

进入条件:控制条件为“真”

退出条件:控制条件为“假”

expr3: 修正控制变量

示例:求100以内所有正整数之和;

#!/bin/bash#declare -i sum=0for ((i=1;i<=100;i++)); do    let sum+=$idoneecho "Sum: $sum."

函数的介绍:

function: 功能

把一段具有独立功能代码封装在一起,并给予命名;后续用到时,可直接通过给定函数名来调用整体代码;函数作用:代码重用和模块化编程;

函数的使用方法:

      先定义:编写函数代码  后调用:给出函数名,还可按需传递参数

      定义方法:

(1) function f_name {

函数体

}

(2) f_name() {

函数体

}

调用函数:

f_name [argu1, argu2, ...]

自定义函数状态返回值:

return [#]

0: 成功

1-255:失败

注意:函数代码执行时,一旦遇到return,函数代码终止运行,函数返回;

示例:此前的if 和case服务脚本可以换成函数简化

#!/bin/bash#prog=$(basename $0)lockfile="/var/lock/subsys/$prog"#echo $lockfileif [ $# -lt 1 ]; then    echo "Usage: $prog start|stop|restart|status"    exit 1fistart() {    if [ -f $lockfile ]; thenecho "$prog is started yet."    elsetouch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."    fi}stop() {    if [ -f $lockfile ]; thenrm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."    elseecho "$prog is stopped yet."    fi}restart() {    if [ -f $lockfile ]; thenrm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."    elsetouch $lockfile && echo "$prog is stopped, Starting $prog ok...."    fi}status() {    if [ -f $lockfile ]; thenecho "Running..."    elseecho "Stopped..."    fi}case $1 instart)    start     ;;stop)    stop    ;;restart)    restart    ;;status)    status    ;;*)    echo "Usage: $prog start|stop|restart|sttus"    exit 1esac

示例:判断用户的ID号的奇偶性;

#!/bin/bash#evenid() {    if [ $# -lt 1 ]; thenreturn 1    fi    if ! id $1 &> /dev/null; then return 2    fi    userid=$(id -u $1)    if [ $[$userid%2] -eq 0 ]; thenecho "$1, Even user ID."    elseecho "$1, Odd user ID."    fi}