shell编程 判断结构语句(if、case)

一、if 语句
if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。
Shell 有三种 if ... else 语句:
if ... fi 语句;
if ... else ... fi 语句;
if ... elif ... else ... fi 语句。
 
语法格式:
if [ expression ]
then
Statement(s) to be executed if expression is true
fi
 
## 注意, expression 和方括号([ ])之间必须有空格,否则会有语法错误。
 
if [ expression ]
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi
 
## 如果 expression 返回 true,那么 then 后边的语句将会被执行;否则,执行 else 后边的语句。
## 如果 then 和 if [ expression ]同一行,则[ expression ]和then之间必须有 ;
 
if [ expression 1 ]
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
fi
 
 
二、if语句的运算符
必须记得:运算符和表达式之间必须有空格,例如2+2是不正确的,它应该写成2 + 2。
 
1、关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
数字比较
-eq 等于,如:if [ "\$a" -eq "\$b" ]
-ne 不等于,如:if [ "\$a" -ne "\$b" ]
-gt 大于,如:if [ "\$a" -gt "\$b" ]
-ge 大于等于,如:if [ "\$a" -ge "\$b" ]
-lt 小于,如:if [ "\$a" -lt "\$b" ]
-le 小于等于,如:if [ "\$a" -le "\$b" ]
 
字符串比较
= 等于,如:if [ "\$a" = "\$b" ]
== 等于,如:if [ "\$a" == "\$b" ],与=等价
!= 不等于,如:if [ "\$a" != "\$b" ]
 
注意: [[]]和[]中的行为在某些情况下是不同的:
 
[[ \$a == z* ]] # 如果\$a 以"z"开头(模式匹配)那么将为true
[[ \$a == "z*" ]] # 如果\$a 等于z* (字符匹配),那么结果为true
 
[ \$a == z* ] # File globbing 和word splitting 将会发生
[ "\$a" == "z*" ] # 如果\$a 等于z* (字符匹配),那么结果为true
 
!= 不等于,如:if [ "\$a" != "\$b" ]
注意:!= 在[[]]结构中使用模式匹配.
 
< 小于,在ASCII 字母顺序下.如:
if [[ "\$a" < "\$b" ]]
if [ "\$a" \< "\$b" ]
注意:在[]结构中"<"需要被转义.
 
> 大于,在ASCII 字母顺序下.如:
if [[ "\$a" > "\$b" ]]
if [ "\$a" \> "\$b" ]
注意:在[]结构中">"需要被转义.
 
 
注意:在[] 表达式中,常见的>,<需要加转义字符,表示字符串大小比较,以acill码 位置作为比较。 不直接支持<>运算符,还有逻辑运算符|| && 它需要用-a[and] –o[or]表示
注意:[[]] 运算符只是[]运算符的扩充。能够支持<,>符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| &&
 
2、逻辑运算符(布尔运算符)
! 非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-a 逻辑与
exp1 -a exp2 如果exp1 和exp2 都为true 的话,这个表达式将返回true
-o 逻辑或
exp1 -o exp2 如果exp1 和exp2 中有一个为true 的话,那么这个表达式就返回true
 
注意,-a 和 -o 放在[] 内部。
 
但在[[]]使用 &&和| | 代替-a 和-o, -o 和-a 一般都是搭配test 命令或者[]
语法格式:
if [ 条件判断一 ] && (||) [ 条件判断二 ]; then
elif [ 条件判断三 ] && (||) [ 条件判断四 ]; then
else
执行第三段內容程式
fi
 
if [ ! "\$repo" ] || [ ! "\$distro" ]; then
.........
fi
 
-O file exists and is owned by the user ID of this process.
[[ \$a == "z*" ]] # 如果\$a 等于z* (字符匹配),那么结果为true
 
 
3、判断上一个语句是否执行成功
shell中使用符号 “\$?” 来显示上一条命令执行的返回值,如果为0则代表执行成功,其他表示失败。
结合if-else语句实现判断上一个命令是否执行成功。
示例:
ls ./
if [ \$? -eq 0 ]; then
    echo "succeed"
else
    echo "failed"
fi
# 上述 if 语句可以写为一行,例如:
if [ \$? -eq 0 ]; then echo "succeed"; else echo "failed"; fi
 
 
三、Linux shell中文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。
 
-a file exists.
-b file exists and is a block special file. 文件是个块设备(软盘,cdrom 等等)
-c file exists and is a character special file. 文件是个字符设备(键盘,modem,声卡等等)
-d file exists and is a directory. 检测文件是否是目录,如果是,则返回 true。
-e file exists (just the same as -a). 文件存在
-f file exists and is a regular file. 一般文件是否存在。
-g file exists and has its setgid(2) bit set. 检测文件是否设置了 SGID 位,如果是,则返回 true。
-G file exists and has the same group ID as this process.
-k file exists and has its sticky bit set. 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。
-L file exists and is a symbolic link. 检测文件是否是symbolic link文件
-n string length is not zero.
-o Named option is set on.
-O file exists and is owned by the user ID of this process.
-p file exists and is a first in, first out (FIFO) special file or named pipe.
-r file exists and is readable by the current process.
-s file exists and has a size greater than zero. 文件是否存在并且是否为非空,不为空返回 true。
-S file exists and is a socket.
-t file descriptor number fildes is open and associated with a terminal device.
-u file exists and has its setuid(2) bit set. 检测文件是否设置了 SUID 位,如果是,则返回 true。
-w file exists and is writable by the current process.
-x file exists and is executable by the current process.
-z string length is zero.
 
-z 检测字符串长度是否为0,为0返回 true。
-n 检测字符串长度是否不为0,不为0返回 true。注意,使用-n在[]结构中测试必须要用""把变量引起来.
str 检测字符串是否为空,不为空返回 true。如 [ \$a ] 返回 true。
注意: 对于字符串或数字的比较, 加上双引号("")是没有坏处的, 而且能避免一些不必要的麻烦(但模式和正则表达式不能加双引号. )
 
 
# 判断一个文件是否存在且是否为空:
if [ -e \$result -a ! -s \$result ];then
echo "empty"
fi
 
# shell判断文件、目录是否存在或者具有权限
例如:
#!/bin/sh
mypath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"
# 这里的-x 参数判断\$myPath是否存在并且是否具有可执行权限
if [ ! -x "\$myPath" ]; then
mkdir "\$myPath"
fi
 
# 这里的-d 参数判断\$myPath是否为目录
if [ ! -d "\$myPath" ]; then
mkdir "\$myPath"
fi
 
# 这里的-f参数判断\$myFile是否存在
if [ ! -f "\$myFile" ]; then
touch "\$myFile"
fi
 
# 其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n "\$myVar" ]; then
echo "\$myVar is empty"
exit 0
fi
 
# 两个变量判断是否相等
if [ "\$var1" = "\$var2" ]; then
echo '\$var1 eq \$var2'
else
echo '\$var1 not eq \$var2'
fi
 
四、变量判断的一些说明
shell的几个小要点:
1、定义变量时,变量名前不用加 \$.如:
declare -A array ## 定义一个关联数组array
但是引用变量的值时,需要在变量名前添加 \$. 如:
echo -e \${array[0]}
 
2、变量赋值时,= 两边不能有空格,否则内核会视为其他操作。
 
3、将shell变量等于命令的结果
方法一: 使用符号 ``
a=`date`
方法二:
a=\$(date)
例如: file=\$(readlink -f \$1)
 
先写一些基本语法:
1、字符串判断
= 等于,如:if [ "\$a" = "\$b" ]
== 等于,如:if [ "\$a" == "\$b" ],与=等价
str1 = str2      
当两个串有相同内容、长度时为真
str1 != str2      当串str1和str2不等时为真
-n str1        当串的长度大于0时为真(串非空)
-z str1        当串的长度为0时为真(空串)
str1         当串str1为非空时为真
 
2、数字的判断
int1 -eq int2    两数相等为真
int1 -ne int2    两数不等为真
int1 -gt int2    int1大于int2为真
int1 -ge int2    int1大于等于int2为真
int1 -lt int2    int1小于int2为真
int1 -le int2    int1小于等于int2为真
 
3 文件的判断
-r file     用户可读为真
-w file     用户可写为真
-x file     用户可执行为真
-a file file是否exists
-e file (just the same as -a). 文件是否存在
-f file     文件为正规文件为真
-d file     文件为目录为真
-c file     文件为字符特殊文件为真
-b file     文件为块特殊文件为真
-s file     文件存在且文件大小非0时为真
-t file     当文件描述符(默认为1)指定的设备为终端时为真
 
3、复杂逻辑判断
-a         与
-o        或
!        非
 
 
五、判断一个变量是否为空
可以通过如下方式判断一个shell变量是否为空:
1. 变量通过" "引号引起来
如下所示:,可以得到结果为 IS NULL.
#!/bin/sh
para1=
if [ ! -n "\$para1" ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi
 
2. 直接通过变量判断
如下所示:得到的结果为: IS NULL
#!/bin/sh
para1=
if [ ! \$para1 ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi
 
3. 使用test判断
得到的结果就是: dmin is not set!
#!/bin/sh
dmin=
if test -z "\$dmin"
then
echo "dmin is not set!"
else
echo "dmin is set !"
fi
 
4. 使用""判断
#!/bin/sh
dmin=
if [ "\$dmin" = "" ]
then
echo "dmin is not set!"
else
echo "dmin is set !"
fi
 
 
六、case语句
case ... esac 是一种多分枝选择结构。
case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:
 
case 值 in
模式1)
command1
command2
;;
模式2)
command1
command2
;;
*)
command1
command2
;;
esac
 
case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。
 
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
匹配模式中可使用方括号表示一个连续的范围,如[0-9];使用竖杠符号“|”表示或。[]是专门针对单字符的值,如果用[no],就是n和o之一。
 
if, case,匹配字符串最常见,但如何匹配一段很长的输出,一堆文字?最好方法,用“*”,如:*"command not found"*
 
例子:
#!/bin/bash
case \$1 in
dog)
echo cat ;;
cat)
echo dog ;;
*)
echo "/root/script.sh cat|dog"
;;
esac
 
 
#!/bin/bash
getyn() { # 构建getyn函数
while echo "enter y/n :"
do
read yn
case \$yn in
[yY]) return 0 ;;
[nN]) return 1 ;;
* ) echo "only accept Y,y,N,n" ;;
esac
done
}
 
if getyn # 调用函数。以函数作为if条件,必须用if command 法,不能有[]
then
echo "your answer is yes"
else
echo "your anser is no"
fi
 
 
posted @ 2022-11-08 11:06  前进吧达瓦里希  阅读(221)  评论(0编辑  收藏  举报