Linux Shell之五 流程控制--选择

简介:

    流程控制可根据不同的情况做不同的处理,而且可重复执行指定的程序区域,展现程序的生产力。在Bash Shell中,流程控制可以分为两大类:

“选择”和“循环”;

1、选择:if、case、select

2、循环:for、while、until、select

命令select既属选择也属于循环。

一、命令的结束状态

在Shell中每一个命令执行后,都会传回一个结束状态值,只分两种,如果成功,传回0,失败则传回非0.

当命令执行后,用$?来查看状态返回值,当在Shell进行条件测试的时候$?=0为真,$?=非0为假。

1
2
3
4
5
6
7
8
[root@Shell ~] # pwd
/root
[root@Shell ~] # echo $?
0
[root@Shell ~] # pwdddd
- bash : pwdddd:  command  not found
[root@Shell ~] # echo $?
127

当一个命令正常执行的时候,$?=0.当一个命令输入错误的时候,$?=非0

比如yum安装软件、复制文件、删除文件、判断文件是否存在等..如果正确执行,则$?=0,如果中间出错,$?=非0


二、if条件判断

if 条件测试;then

命令区域

fi

如果"条件测试"为真,就执行"命令区域"的指令,否则继续fi下一行指令。

1
2
3
4
5
6
7
8
[root@Shell ~] # cat test.sh 
#!/bin/bash
#
if  grep  -q ^root  /etc/passwd ; then
echo  "The user root is exist"
fi
[root@Shell ~] # bash test.sh 
The user root is exist

使用grep在/etc/passwd搜索以root开头的关键词,如果为真,就继续执行下边的命令(grep -q表示只判断真假,不作输出)。

最简单的if语法:if-then-else

if 条件测试;then

命令区域1

else

命令区域2

fi

如果"条件测试"为真,就执行"命令区域1"的指令,否则就执行"命令区域2"的指令。

1
2
3
4
5
6
7
8
9
10
[root@Shell ~] # cat test.sh 
#!/bin/bash
#
if  grep  -q ^roothi  /etc/passwd ; then
echo  "The user roothi is exist"
else
echo  "The user roothi not exist"
fi
[root@Shell ~] # bash test.sh 
The user roothi not exist

判断用户roothi是否存在。

if的完整语法

if   条件测试1;then

 命令区域1

elif  条件测试2;then

 命令区域2

else  

 命令区域3

fi

如果条件测试1为真,则执行命令区域1,如果为假,则执行条件测试2;如果条件测试2为真,则执行命令区域2,如果条件测试2为假,则执行命令区域3(elif条件可以有多个)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@Shell ~] # ./test.sh 5 2
5 is the bigger!
[root@Shell ~] # ./test.sh 5 10
10 is the bigger!
[root@Shell ~] # ./test.sh 5 5
5 = 5 
[root@Shell ~] # cat test.sh 
#!/bin/bash
#
declare  -i a b    #声明a b都在正整数
a=$1
b=$2
if  (( $a > $b )); then
echo  $a is the bigger!
elif  (( $a < $b )); then
echo  $b is the bigger!
else
echo  "$a = $b "
fi


三、条件测试的写法

条件测试的写法有10种。(传回结果0为真值,非0为假值)

1、执行某一个命令的结果。

   if grep -q "root" /etc/passwd;then (-q 静默,只为判断$?)

      echo "root is exist"

其结束状态为最后一个命令执行的结果

2、传回某一命令结果的相反值。

   ! 命令(中间要用空格隔开)

   if ! grep -q "root" /etc/passwd;then (-q 静默,只为判断$?)

      echo "root is not exist"

如果命令传回结果为0,则加上!之后传回值为1;反之如果命令传回值为非0,则加上!之后传回值为0

3、使用复合命令((算式))

   运算结果不为0为真,为0为假

   ((8*3)) 24 真

   ((5-5)) 0  假

   ((20<30))  真 

   ((20>30))  假

   ((20&&30)) 真

   ((20&&0))  假   

4、使用Bash关键字'[[  ]]'组成的句子:[[ 判断式 ]]

   [[ 后和 ]]前至少有一个空格 

   if [[ str > xyz ]];then

      echo "字符串str比较大"

5、使用内置命令:test判断式

   if test "str" \> "xyz";then                     (>为特殊字符,用\转义)

      echo "字符串str比较大"

6、使用内置命令:[ ]判断式

   [] 与test用法相同

   if [ "str" \> "xyz" ];then                     (>为特殊字符,用\转义)

      echo "字符串str比较大"  

7、使用-a、-o进行逻辑组合

   [ -r filename -a -x filename] 如果filename可读且可执行,则为真。-a,且。

   [ -r filename -o -x filename] 如果filename可读或可执行,则为真。-o,或。

8、命令1&&命令2

   命令1真才执行命令2,都真传回值0,否则1

  if grep -q "root" /etc/passwd && ((8<10));then

9、命令1||命令2

   命令1假才执行命令2,如果一个命令或都为真传回值0,否则1

   ((2<3))||((4<5));then  

10、$$和||合用

   如果是 “[ 判断式 ] &&指令1||指令2”形式,视为 if-then-else 

   [ "2" \> "1" ]&& echo "right"||echo "error"等同于等同于以下脚本:

   if [ "2" \> "1" ];then

     echo "right"

  else

     echo "error"

   fi

总结:

` `、test、[]用法意思相近,但` `更自由(不必担心特殊符号,不必转义),(())也不受特殊符号影响。

在[[判断式]]中,如果使用==或!=且右方的字符串没有使用单引号、双引号,则视为对比该字符串形成的“样式”,如果相符,传回0,否则1。

!/bin/bash

a="str"

if [[ $a == ??? ]];then    意思是:用$a的值,对比样式???(3个字符串) 

  echo "hello"

fi

上边如果把if行改为 

if [[ $a == "???" ]];then  意思是:用$a和字符串???是否相等 


四、条件判断式的真假值

判断式:影响程序流程的式子,判断式分为“单元”和“二元”

如  -f filename ,测试文件是否存在。-f后跟一个操作数的文件称为“单元”。

如 参数1 -gt 参数2,测试参数1值是否大于参数2,-gt左右各接一个要比较的参数,这种判断式称为“二元”。

--------------------关于文件的判断式--------------------

判断式                  什么情况下为真

-a/e 文件存在

-b   文件存在,且文件是区域设备文件

-c   文件存在,且文件是字符设备文件

-d   文件存在,且文件是目录

-p   文件存在,且该文件是管道文件(FIFO)

-f   文件存在,且该文件是一般文件

-g   文件存在,且该文件设立了 set group id属性 -u uid

-h/L 文件存在,且该文件是符号链接文件

-r   文件存在,且该文件有可读取的属性 -w 可写 -x 可执行

-s   文件存在,且该文件大小大于0(文件存在,且文件有数据)

-t   文件描述符   如果文件描述符是开启的,且链接了某一个终端

-S   文件存在,且该文件是socket文件

-N   文件存在,且该文件从上次读取后,曾修改过。

文件1  -nt 文件2   如果文件1比文件2新;文件1存在,但文件2不存在。

文件1  -ot 文件2   如果文件1比文件2旧;文件1不存在,但文件2存在。

文件1  -ef 文件2   如果文件1和文件2 参考到相同的设备和inode编号。

--------------------关于字符串的条件判断式--------------

判断式                        什么情况下为真

-z 长度为0(即空字符串)

-n 长度不为0(即非空字符串)

字符串字符串长度不为0

==和=代表相同(左右两边分别有个字符串)

!= 不等  < 小于  > 大于 (如果<>出现在[]或test中的时候,要用\转义)

--------------------关于算式的条件判断式----------------

-eq   相等

-ne   不相等

-lt   小于

-le   小于或等于

-gt   大于

-ge   大于或等于

-------------------关于Bash选项的条件判断式-------------------

-o   set选项的名称 如果该选项为开启状态则为真。

!/bin/bash

set -o

if [ -o history ];then

  echo 'Bash选项history开启'

else

  echo 'Bash选项history关闭'

fi


五、case条件判断

if条件判断中提到的if条件判断,一旦要进行的条件测试的情况多了起来,if和elif的语法就会变得很冗长,case条件判断语法可补其不足。

------------------case的语法结构------------------

case 待测项 in

   样式串行1 )命令区域1;;

   样式串行2 )命令区域2;;

   样式串行3 )命令区域3;;

   .....

   *) 命令区域;;

esca

样式串行可以是字符串:如a、b、mary

              通配符:*任意长度(包括空字符)  ?一个字符

              字符集合:[a-d]mm,表示amm、bmm、cmm、dmm

              分隔符:|             

如果待测项与样式串行符合的话,case会执行该样式后的命令区域,命令区域可以是单一指令或多行指令,最后以;;结束。

样式串行可以用字符串和通配符组成,默认会区别大小写。

如果串行有好几个字符要对比,用|隔开,|有或的意思(只要符合其中之一就算成功)。

样式串行可以写为'(样式串行)'或'样式串行'

*)通常放在case最后的一个区域,用来谱捉不符合指定样式的其它情况。

例子:

!/bin/bash

name=$1                                      第一个输入的参数附给name 

case $name in

  a|b|c)                                      匹配的选项1,变量为a或b或c的时候

     echo "hello,abc group"                   输出结果1

    ;;                                        ;;可放到输出结果1后,也可另起一行

  huan)                                       匹配选项2 ,变量为huan的时候

     echo "i love you"                        输出结果2

    ;;

  s*)                                         匹配选项3,变量以s开头的字符串

    echo "you are first s"                    输出结果3

    ;;

  *)                                          匹配选项4 不符合上边任何条件的字符串

    echo "what is this?";;                输出结果4 "what is this?".......    

esca      结束

-----------------高级样式--------------------

样式    符合情况

?(样式串行) 符合0个或1个

*(样式串行) 符合0个以上

+(样式串行) 符合1个以上

@(样式串行) 符合其中1个

!(样式串行) 只要不是出现在括号里的样式就算符合      

j@(ac|xy|pq)k|join|joe echo 'hello';;

只要变量符合jack、jxyk、jpqk、join、joe其中之一就算符合

if [[ $cmd == @(a|b) ]];then 

只要是a或b就算是对比成功。


本文转自Jacken_yang 51CTO博客,原文链接:http://blog.51cto.com/linuxnote/1641204,如需转载请自行联系原作者

相关文章
|
3月前
|
存储 安全 Unix
七、Linux Shell 与脚本基础
别再一遍遍地敲重复的命令了,把它们写进Shell脚本,就能一键搞定。脚本本质上就是个存着一堆命令的文本文件,但要让它“活”起来,有几个关键点:文件开头最好用#!/usr/bin/env bash来指定解释器,并用chmod +x给它执行权限。执行时也有讲究:./script.sh是在一个新“房间”(子Shell)里跑,不影响你;而source script.sh是在当前“房间”里跑,适合用来加载环境变量和配置文件。
420 9
|
3月前
|
算法 Linux Shell
Linux实用技能:打包压缩、热键、Shell与权限管理
本文详解Linux打包压缩技巧、常用命令与原理,涵盖.zip与.tgz格式操作、跨系统传文件方法、Shell运行机制及权限管理,助你高效使用Linux系统。
Linux实用技能:打包压缩、热键、Shell与权限管理
|
3月前
|
存储 Shell Linux
八、Linux Shell 脚本:变量与字符串
Shell脚本里的变量就像一个个贴着标签的“箱子”。装东西(赋值)时,=两边千万不能有空格。用单引号''装进去的东西会原封不动,用双引号""则会让里面的$变量先“变身”再装箱。默认箱子只能在当前“房间”(Shell进程)用,想让隔壁房间(子进程)也能看到,就得给箱子盖个export的“出口”戳。此外,Shell还自带了$?(上条命令的成绩单)和$1(别人递进来的第一个包裹)等许多特殊箱子,非常有用。
310 3
|
4月前
|
存储 Linux
Linux环境下删除大文件后磁盘空间未释放问题诊断流程。
以上诊断流程涉及Linux底层机制与高级管理技能结合之处,并需要管理员根据实际环境灵活调整诊断策略与解决方案。
266 8
|
5月前
|
Web App开发 缓存 安全
Linux一键清理系统垃圾:释放30GB空间的Shell脚本实战​
这篇博客介绍了一个实用的Linux系统盘清理脚本,主要功能包括: 安全权限检查和旧内核清理,保留当前使用内核 7天以上日志文件清理和系统日志压缩 浏览器缓存(Chrome/Firefox)、APT缓存、临时文件清理 智能清理Snap旧版本和Docker无用数据 提供磁盘空间使用前后对比和大文件查找功能 脚本采用交互式设计确保安全性,适合定期维护开发环境、服务器和个人电脑。文章详细解析了脚本的关键功能代码,并给出了使用建议。完整脚本已开源,用户可根据需求自定义调整清理策略。
567 0
|
7月前
|
Linux Shell
Centos或Linux编写一键式Shell脚本删除用户、组指导手册
Centos或Linux编写一键式Shell脚本删除用户、组指导手册
200 4
|
7月前
|
Linux Shell 数据安全/隐私保护
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
404 3
|
8月前
|
Linux Shell
在Linux、CentOS7中设置shell脚本开机自启动服务
以上就是在CentOS 7中设置shell脚本开机自启动服务的全部步骤。希望这个指南能帮助你更好地管理你的Linux系统。
631 25
|
8月前
|
Linux Shell
shell_42:Linux参数移动
总的来说,参数移动是Linux shell脚本中的一个重要概念,掌握它可以帮助我们更好地处理和管理脚本中的参数。希望这个解释能帮助你理解和使用参数移动。
171 18
|
10月前
|
Shell Linux
【linux】Shell脚本中basename和dirname的详细用法教程
本文详细介绍了Linux Shell脚本中 `basename`和 `dirname`命令的用法,包括去除路径信息、去除后缀、批量处理文件名和路径等。同时,通过文件备份和日志文件分离的实践应用,展示了这两个命令在实际脚本中的应用场景。希望本文能帮助您更好地理解和应用 `basename`和 `dirname`命令,提高Shell脚本编写的效率和灵活性。
732 32