SHELL-流程控制

SHELL脚本-流程控制

1 if-then语句-判断

1.1 基本结构

if command;then
  commands
fi

该结构的if语句可以用于判断if后的command是否执行成功,当该command执行成功(状态返回码为0),则执行then后的语句,否则退出。

if command;then
  commands
else
  commands
fi

该结构的if语句与上一结构功能类似,只是当command执行不成功的时候,执行else后的语句。

1.2 嵌套if

if command;then
  commands
elif command;then
  commands
else 
  commands
fi

这种嵌套的if语句,使用elif用于测试另外的命令,如果if后的command退出状态码为非0,则会测试elif后的命令,如果elif后的命令退出状态码为0则会执行,elif后的then语句,否则执行else语句。所以紧跟在elif语句的else语句,是属于elif的代码块,而不是if-then的代码块。

通过将多个elif语句联合起来,可以形成一个大规模的if-then-elif的嵌套组,从而实现类似于case语句的功能。

if command;then
  commands
elif command;then
  commands
elif command;then
  commands
elif command;then
  commands
fi

1.3 if的条件判断

与其他高级语言相同,if语句不仅可以根据命令的执行状态进行选择判断,也可以通过判断条件是否成立执行命令。

尽管if语句中的条件判断可以通过test命令实现,但最常使用的条件判断方法是使用方括号。

if [ condition ];then
  commands
else
  commands
fi

通过方括号执行条件判断需要注意的是,在条件判断语句和方括号左右两边均有空格隔开。

1.3.1 数值比较

假定变量 a 为 5,变量 b 为 10:

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

1.3.2 字符串比较

下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ] 返回 true。
$ 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

1.3.3 文件比较

操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

其他检查符:

  • -S: 判断某文件是否 socket。
  • -L: 检测文件是否存在并且是一个符号链接。

1.4 if-then的高级特性

  • 通过使用双方括号不仅可以使用标准的字符串比较,也可以通过正则表达式匹配字符。
  • 通过使用双括号可以使用任意的书序赋值或比较表达式,双括号用到的其他运算符如下表
符号 描述
val++ 后增
val-- 后减
++val 先增
--val 先减
逻辑求反
~ 位求反
** 幂运算
<< 左位移
>> 右位移
& 位布尔和
| 位布尔或
&& 逻辑和
|| 逻辑或

1.5 case 语句

case var in
pattern1)
  commands1
  ;;
pattern2)
  commands2
  ;;
*)
  commands3
  ;;
esac

case语句用于匹配同一变量的不同值,避免了使用if-then-elif的循环嵌套导致的逻辑混乱。语法结构更加清晰。

2 for while 循环语句

2.1 for语句基本格式

for var in list;do 
 commands 
done

在list参数中,你需要提供迭代中要用到的一系列值。可以通过几种不同的方法指定列表 中的值。

在每次迭代中,变量var会包含列表中的当前值。第一次迭代会使用列表中的第一个值,第 二次迭代使用第二个值,以此类推,直到列表中的所有值都过一遍。

在do和done语句之间输入的命令可以是一条或多条标准的bash shell命令。在这些命令中, $var变量包含着这次迭代对应的当前列表项中的值。

list的值可以是数字,也可以是字符串。列表的值可以是由自己定义而来的,也可以是命令执行后的结果。常见的几种迭代定义方法:

#var值由192.168.1.2-192.168.1.150中循环迭代
for var in 192.168.1.{2..150}    
#var值迭代文件夹/etc/下的所有文件或目录(通配符方法)
for var in /etc/*
#var值迭代文件夹/etc/下的所有文件或目录
for var in $(ls /etc)
#var值迭代1-6
for var in {1..6}

2.2 更改字段分隔符

for迭代字符串的中各个字符串的方法是由一个特殊的环境变量IFS定义的,默认的情况下bash shell会将下列字符当做字段分隔符:

  • 空格
  • 制表符
  • 换行符

可以在shell脚本中定义IFS的值变更分割符号如IFS=:

在处理代码量较大的脚本时,可能在一个地方需要修改IFS的值,然后忽略这次修改,在
脚本的其他地方继续沿用IFS的默认值。一个可参考的安全实践是在改变IFS之前保存原
来的IFS值,之后再恢复它。
这种技术可以这样实现:
 IFS.OLD=$IFS 
 IFS=$'\n' 
 <在代码中使用新的IFS值> 
 IFS=$IFS.OLD 
这就保证了在脚本的后续操作中使用的是IFS的默认值

2.3 C语言风格的for循环

在shell脚本中可以通过双括号实现C语言风格的for循环,如:for (( i=1; i <= 10; i++ ))

for循环通过定义好的变量(本例中是变量i)来迭代执行这些命令。在每次迭代中,$i变 量包含了for循环中赋予的值。在每次迭代后,循环的迭代过程会作用在变量上,在本例中,变 量增一。

也可以同时迭代两个变量如:for (( a=1, b=10; a <= 10; a++, b-- ))

2.4 while循环

while循环可以视作某种if-then与for循环的混杂体。对while循环设置一个跳出循环条件,如果不符合条件将一直循环下去。设置条件的方式和if-then语句完全一样。需要注意的是当设置条件的时候,需要明确自己是需要一个死循环还是有限循环,并根据设计的目的,添加变量迭代方式。

while循环的基本结果如:

while test command ;do 
 other commands 
done 

通过while ture可以实现代码的死循环,当然即使设置死循环也需要通过break设置跳出循环的条件。

2.5 until循环

until命令和while命令工作的方式完全相反。until命令要求你指定一个通常返回非零退 出状态码的测试命令。只有测试命令的退出状态码不为0,bash shell才会执行循环中列出的命令。 一旦测试命令返回了退出状态码0,循环就结束了。

until的基本格式如:

untile test command;do
  other commands
done

2.6 控制循环

你可能会想,一旦启动了循环,就必须苦等到循环完成所有的迭代。并不是这样的。有两个 命令能帮我们控制循环内部的情况:

  • break
  • continue

break命令可以直接跳出循环,不执行剩余的迭代任务。break默认只跳出一层循环,如果有嵌套循环的存在,需要跳出多层循环,可以通过break n。n为1,表明跳出的是当前的循环(这也是默认设置)。如果你将 n设为2,break命令就会停止下一级的外部循环。

continue命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。在当前循环中,剩余的命令将不会被执行,而直接进入下一次的循环。

posted @ 2022-04-19 11:05  残-云  阅读(99)  评论(0编辑  收藏  举报