shell编程之条件语句(条件测试、if语句、case语句、循环语句)

157 阅读2分钟

条件测试

测试格式

 格式一: test 条件表达式
 ​
 格式二: [ 条件表达式 ]  #注意前后空格

两种方式作用相同,后一种形式更为常用。 执行条件测试操作后,通过预定义变量“$?”可以获得测试命令的返回状态值,条件成立,为0,否则为1

文件测试

常用的文件测试操作符:

操作符作用
-d测试文件是否为目录文件(Directory)
-f测试文件是否为普通文件(File)
-e测试目录或文件是否存在(Exist)。建议使用-e,-a可能不准确。
-a测试目录或文件是否存在(Exist)
-r测试当前用户是否有权限读取(Read)
-w测试当前用户是否有权限写入(Write)
-x测试当前用户是否有权限执行(eXcute)
-L测试是否为符号链接(软链接文件)
-nt判断文件A是否比文件B新
-ot判断文件A是否比文件B旧
-ef判断两个文件是否为同一文件。可用于硬链接,主要判断两个文件是否指向同一个inode。

属性测试补充:

操作符作用
-s FILE判断文件是否存在且非空
-t fdfd 指定文件描述符是否在某终端已经打开
-N FILE文件自从上一次被读取之后是否被修改过
-O FILE当前有效用户是否为文件属主
-G FILE当前有效用户是否为文件属组
[root@localhost ~]#ll /etc/shadow
---------- 1 root root 1549 1019 10:58 /etc/shadow
[root@localhost ~]#[ -r /etc/shadow ]
[root@localhost ~]#echo $?
0
#实际效果,不是表面显示,注意root权限
[root@localhost ~]#[ -x /etc/shadow ]
[root@localhost ~]#echo $?
1

root执行权限别人没有root也没有,别人有root也有

整数值比较

操作符含义
-eq等于(Equal)
-ne不等于(Not Equal)
-gt大于(Greater Than)
-lt小于(Lesser Than)
-le小于或等于(Lesser or Equal)
-ge大于或等于(Greater or Equal)

字符串比较

常用的测试操作符

  • =:字符串内容相同
  • !=:字符串内容不同,! 号表示相反的意思
  • -z:字符串内容为空
  • -n:字符是否存在

字符串比较,常用的四种格式:

 [ "字符串1"  =  "字符串2"  ]   //测试字符串1和字符串2的内容是否相同
 [ "字符串1" !=  "字符串2”  ]   //测试字符串1和字符串2的内容是否不同
 [ -z "字符串" ]    //测试字符串是否为空,或者指定的变量是否为空值。(测试字符串的长度是否为零)
 [ -n "字符串" ]    //测试字符串是否存在,即是否不为空。(测试字符串的长度是否非零)

逻辑测试

逻辑运算符:

  • -a或&& :逻辑与,“而且”的意思,全真才为真。
  • -o或|| :逻辑或,“或者”的意思,一真即为真。
  • ! :逻辑否。

1)短路与 &&

 CMD1 && CMD2 
 全真才为真,一假即为假。      
 第一个CMD1结果为真 ,第二个CMD2必须要参与运算,才能得到最终的结果。
 第一个CMD1结果为假 ,总的结果必定为假,因此不需要执行CMD2。
 同时满足命令1 和命令2 的要求,才会返回正确。

2)短路或 ||

 CMD1 || CMD2
 一真即为真
 第一个CMD1结果为真,总的结果必定为真,因此不需要执行CMD2。
 第一个CMD1结果为假,第二个CMD2必须要参与运算,才能得到最终的结果。

3)三元运算符

 [ 表达式 ] && a || b
 
 当表达式为真时,取a值;当表达式为假时,取b值。
[表达式1] && [表达式2] 等同于 [表达式1 -a 表达式2] 等同于 [[表达式1 && 表达式2]]  
 
[表达式1] || [表达式2] 等同于 [表达式1 -o 表达式2] 等同于 [[表达式1 || 表达式2]]

() {}

(CMD1;CMD2;...)和 {空格CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

#()会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#( echo $BASHPID;sleep 100)
1979
#{ } 不会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#{ echo $BASHPID; }
1920



[root@localhost data]#name=lc
[root@localhost data]#( name=mcl;echo $name );echo $name
mcl
lc
[root@localhost data]#name=lc
[root@localhost data]#{ name=mcl;echo $name; };echo $name
mcl
mcl

if语句的结构

单分支

if 判断条件;

then   
  条件为真的分支代码

fi

双分支

if 判断条件; 
then
 条件为真的分支代码

else
 条件为假的分支代码

fi

多分支


if 判断条件1
then
 条件1为真的分支代码

elif 判断条件2
then
 条件2为真的分支代码

elif 判断条件3;then
 条件3为真的分支代码

...
else
 以上条件都为假的分支代码

fi

case分支语句

格式:

 case 变量引用 in
 模式1)
     命令分支1
     ;;
 模式2)
     命令分支2
     ;;
 ...
 *)
     默认命令分支
 esac

echo命令

echo -n   表示不换行输出

echo -e   表示输出转义符

常用的转义符

选项作用
\r光标移至行首,并且不换行
\s当前shell的名称,如bash
\t插入Tab键,制表符
\n输出换行
\f换行,但光标仍停留在原处
\表示插入"\"本身转义
\b表示退格 不显示前一个字符
\c抑制更多的输出或不换行
[root@localhost ky15]#echo -e "12345\b\b\b\b678"
16785
###注意退格键和末尾的字符相关,超过末尾的字符数量 会出bug 了解即可
[root@localhost ky15]#echo -e "1234\c5678"
1234[root@localhost ky15]#
###\c 注意 使用在数字中间会把后面内容删除

echo -e "n\n\n\n\n\nw"|fdisk /dev/sdb
#自动硬盘分区




[root@localhost data]#rm -rf 123      
#是把软连接删除
[root@localhost data]#rm -rr 123/
#把软连接里的文件全删除

循环语句

for循环

用法:

  • 读取不同的变量值,用来逐个执行同一组命令。
  • 使用场景:一般用于循环次数事先已知的场景。
  • 执行机制:遍历。

格式:

 for 变量名 in 取值列表
 do
    命令序列
 done

 for的三个默认分隔符

环境变量$IFS,是指内部字段分隔符, 默认为三个:空格、制表符 \t、换行符 \n。

若使用for读取文件内容,文件中有空格 在脚本中,先临时将变量IFS的值中的空格删除,使for语句不以空格作为分隔符,最后还原变量值。

 [root@yuji sh]# vim fen2.sh       //写脚本
 #!/bin/bash
 ​
 #借用一个临时变量先保存IFS的原始值
 IFS_OLD=$IFS
 #删除空格和制表符,只保留换行符作为分隔符
 IFS=$'\n'
 ​
 #从文件中获取变量值,$()表示调用命令执行的结果
 for name in $(cat name.txt)
 do
    echo "$name"
 done
 ​
 #还原变量IFS的原始值
 IFS=$IFS_OLD
 ​
 [root@yuji sh]# cat name.txt    //查看文件内容,只有3行
 zhang san
 lisi
 wang wu
 [root@yuji sh]# bash fen2.sh     //运行脚本,显示3行
 zhang san
 lisi
 wang wu

while

相对于for,需要知道循环次数

我们只知道停止条件,不知道次数,就需要使用while

直到达到条件

格式:

 while  条件测试操作
 do
    命令序列
 done

until

用法:

  • 重复测试某个条件,只要条件不成立则反复执行。

格式:

 until 条件测试操作
 do
    命令序列
 done

continue

continue的作用:

  • 终止某次循环的执行,本次循环continue后面的语句不会执行,但不会完全终止整个循环。就是直接跳过满足条件的循环,即满足条件的不执行。

  • continue一般用于for循环。在while和until中要慎用,因为如果变量迭代语句放在continue之后,那么迭代不会执行,会造成死循环。

break

break的作用:

  • 跳出单层循环,默认为break 1,后面的数字为跳出层数。例如"break 2"为跳出2层循环。
  • 循环内break之后的语句都不会执行,但循环外的语句仍然会执行。4