[Linux][Shell][Shell逻辑控制]详细讲解

DieSnowK 2024-07-28 09:07:02 阅读 53

目录

1.if 判断1.if-then2.if-then-else3.elif4.case5.实际上手

2.条件测试0.事前说明1.test 命令2.[]3.双括号1.(())2.[[]]

4.实际上手

3.循环1.for2.while3.until命令4.控制循环1.break2.continue

5.处理循环的输出


1.if 判断

1.if-then

语法

<code>if command

then

command

fi

bash的if语句和其他编程语言不一样,bash的if语句会直接运⾏if后⾯的命令

如果该命令执⾏正确(状态码为0),处于then的命令就会被执⾏否则就不会执行,或者执行其他逻辑的语句,最后到fi结束逻辑控制

2.if-then-else

语法

if command

then

command

else

command

fi

3.elif

语法

if command

then

command

elif command

then

command

fi

4.case

可以代替多if-else分支

case "变量" in

值1)

命令

;;

值2)

命令2

;;

*)

命令

5.实际上手

内存监控

#!/bin/bash

FreeMem=`free -m | awk 'NR==2 {print $NF}'`

CHARS="Current memory is $FreeMem"code>

if [ "$FreeMem" -lt 16000 ]

then

echo $CHARS

echo "内存不足,抓紧维护服务器!"

fi

读取比较大小

单分支版本

#!/bin/bash

a=$1

b=$2

if [ $a -lt $b ]

then

echo "Yes, $a less than $b"

exit 0

fi

if [ $a -eq $b ]

then

echo "Yes, $a equal $b"

exit 0

fi

if [ $a -gt $b ]

then

echo "Yes, $a greater than $b"

exit 0

fi

多分支版本

#!/bin/bash

a=$1

b=$2

if [ $a -lt $b ]

then

echo "Yes, $a less than $b"

exit 0

elif [ $a -eq $b ]

then

echo "Yes, $a equal $b"

exit 0

else [ $a -gt $b ]

echo "Yes, $a greater than $b"

exit 0

fi

MySQL监控脚本

#!/bin/bash

if [ `netstat -tunlp | grep mysql | wc -l` -ge "1" ]

then

echo "MySQL is running"

else

echo "MySQL is stopped"

# systemctl start mysql.service

fi

Rsync启动脚本

#!/bin/bash

if [ "$#" -ne 1 ]

then

echo "Usage: $0 {start|stop|restart}"

exit 1

fi

if [ "$1" = "start" ]

then

/usr/bin/rsync --daemon

sleep 2

if [ `netstat -tunlp | grep rsync | wc -l` -ge 1 ]

then

echo "Rsync is started"

exit 0

fi

elif [ "$1" = "stop" ]

then

killall rsync &>/dev/null

sleep 2

if [ `netstat -tunlp | grep rsync | wc -l` -eq 0 ]

then

echo "Rsync is stopped"

exit 0

fi

elif [ "$1" = "restart" ]

then

kill rsync

sleep 1

killpro=`netstat -tunlp | grep rsync | wc -l`

/usr/bin/rsync --daemon

sleep 1

startpro=`netstat -tunlp | grep rsync | wc -l`

if [ "$killpro" -eq 0 -a "$startpro" -ge 1 ]

then

echo "Rsync is restarted"

exit 0

fi

else

echo "Usage: $0 {start|stop|restart}"

exit 1

fi


2.条件测试

0.事前说明

条件测试常用的语法

请添加图片描述

常用字符串测试操作符

请添加图片描述

数值比较

请添加图片描述

逻辑操作符

请添加图片描述

命令对照表

请添加图片描述


1.test 命令

<code>test命令最短的定义可能是评估⼀个表达式

如果条件为真,则返回⼀个0值如果表达式不为真,则返回⼀个⼤于0的值—,也可以将其称为假值检查最后所执⾏命令的状态的最简便⽅法是使⽤$?参数

关于某个文件名的类型侦测(存在与否),如:test -e filename

参数 意义
-e 该 文件名 是否存在
-f 该 文件名 是否为文件(file)
-d 该 文件名 是否为目录(directory)
-b 该 文件名 是否为block device装置
-c 该 文件名 是否为一个character device装置
-S 该 文件名 是否为一个Socket文件
-p 该 文件名 是否为一个FIFO(pile)文件
-L 该 文件名 是否为一个连接档

关于文件的权限侦测,如:test -r filename

参数 意义
-r 该 文件名 是否具有可读的属性
-w 该 文件名 是否具有可写的属性
-x 该 文件名 是否具有可执行的属性
-u 该 文件名 是否具有SUID的属性
-g 该 文件名 是否具有SGID的属性
-k 该 文件名 是否具有Sticky bit的属性
-s 该 文件名 是否为非空白文件

关于两个文件之间的比较,如:test file1 -nt file2

参数 意义
-nt (newer than),判断file1是否比file2
-ot (older than),判断file1是否比file2
-ef 判断file1file2是否为同⼀⽂件,可⽤在硬链接的判定上

主要意义在判定,两个⽂件是否均指向同⼀个inode

关于两个整数之间的判定,如:test num1 -eq num2

参数 意义
-eq 两数相等
-ne 两数不相等
-gt num1大于num2
-lt num1小于num2
-ge num1大于等于num2
-le num1小于等于num2

判定字符串的数据

参数 意义
-z 为空串,则返回true
-n 不为空串,则为true
= str1 == str2,则返回true
!= str1 != str2,则返回true

多重条件判断,如:test -r filename -a -x filename

参数 意义
-a (and)两状况同时成立
-o (or)两状况任何一个成立
! 逻辑取反

2.[]

脚本中经常进行条件测试,用的最多的,就是中括号[]test[]的作用是一样的基本要素

[]两个符号,左右都要有空格分隔内部操作符与操作变量之间要有空格,如:[ "a" = "b" ]字符串比较中,> <需要写成\> /<进行转义[]中字符串或者${}变量尽量使用""双引号括住,避免值未定义引用

[ -n "$filename" ]

[]中可以使用-a -o进行逻辑运算,不支持&& ||[]是bash内置命令


3.双括号

1.(())

bash支持双小括号,写入高级数学表达式

2.[[]]

双中括号提供了针对字符串的⾼级特性,模式匹配,正则表达式的匹配基本要素

[[]]两个符号,左右都要有空格分隔内部操作符与操作变量之间要有空格,如:[[ "a" = "b" ]]字符串比较中,可以直接使用> <,无需转义[[]]中字符串或者${}变量尽量使用""双引号括住

如未使用""双引号括住的话,会进行模式和元字符匹配 [[]]内部可以使用&& ||进行逻辑运算[[]]是bash的keyword[[]]其他用法都和[]一样


4.实际上手

测试逻辑判断

#!/bin/bash

read -p "Pls input a char:> " var1

[ "${var1}" -eq 1 ] && {

echo ${var1}

exit 0

}

[ "$var1" -eq 2 ] && {

echo $var1

exit 0

}

[ "$var1" -ne "1" -a "$var1" -ne "2" ] && {

echo "Script Error"

exit 1

}

模拟安装脚本

#!/bin/bash

path=/scripts

[ ! -d "$path" ] && mkdir -p scripts

cat << END

1.[install lamp]

2.[install inmp]

3.[exit]

END

read -p "Pls input your choice:> " num

# 判断输入是否合法

[[ ! $num =~ [1-3] ]] && {

echo "The num you input must be in {1|2|3}"

echo "Input Error"

exit 1

}

[ $num -eq 1 ] && {

echo "start installing lamp...waiting..."

sleep 2

# 如果该脚本没权限

[ ! -x "$path/lamp.sh" ] || {

echo "The file does not exit or can't be exec"

exit 2

}

# 安装脚本

source ${path}/lamp.sh

exit $?

}

[ $num -eq 2 ] && {

echo "start installing lnmp...waiting..."

sleep 2

[ ! -x "$path/lnmp.sh" ] || {

echo "The file does not exit or can't be exec"

exit 3

}

source ${path}/lnmp.sh

exit $?

}

[ $num -eq 3 ] && {

echo "Bye~"

exit 4

}


3.循环

1.for

语法

for var in list

do

commands

done

支持C语言风格

for (( i=1;i<=10;i++ ))

do

echo "The next number is $i"

done


2.while

语法:此处的test commandif-else语句格式一样,可以使用任何的bash命令

注意whiletest command的退出状态码,必须随着循环⾥的命令改变,否则状态码如果不变化,循环会不停⽌的继续下去

while test command

do

commands

done

while命令可以写入多个测试命令

只有最后一个测试命令的退出状态码会被决定是否退出循环注意换行,多个测试命令要单独的出现在每一行

var1=10

while echo $var1

[ $var1 -ge 0 ]

do

echo "This is inside the loop"

var1=$[ $var1 -1 ]

done


3.until命令

untilwhile相反的语意until命令要求你指定⼀个返回⾮零退出码的测试命令

只有退出状态码不是0,bash才会执⾏循环的命令 语法

until test commands

do

other commands

done

until⽀持多个测试命令,只有最后⼀个决定bash是否执⾏其他命令

until echo $var1

[ $var1 -eq 0 ]

do

echo "Inside the loop:$var1"

var1=$[ $var1 - 25 ]

done


4.控制循环

1.break

作用:强制退出任意类型的循环

跳出多个循环时,break会自动终止所在的最内存循环 终止外层循环n表示跳出的循环层级,默认是1,下一层就是2

break n

2.continue

作用:跳过某次循环,直接去本次循环的判断部分


5.处理循环的输出

在shell脚本⾥,循环输出后的结果,可以进⾏输出重定向

for (( a = 1;a<10;a++ ))

do

echo "The number is $a"

done > test.txt

echo "Finished"



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。