shell的结构化命令

摘要:shell在逻辑流程控制这里会根据设置的变量值的条件或者其余命令的结果跳过少量命令或者者循环执行的这些命令。这些命令通常称为结构化命令1、if-then语句详情基本格式if commandthen commandsfi在其余语言中if语句后的对象值为TRUE或者FALSE的等式、bash shell脚本

shell在逻辑流程控制这里会根据设置的变量值的条件或者其余命令的结果跳过少量命令或者者循环执行的这些命令。这些命令通常称为结构化命令


1、if-then语句详情

基本格式if commandthen  commandsfi在其余语言中if语句后的对象值为TRUE或者FALSE的等式、bash shell脚本中的if不是这样的[root@eyu sbin]# sh data.sh 2018年 10月 04日 星期四 18:45:15 CSTecho it worked[root@eyu sbin]# cat data.sh #!/bin/bashif datethenecho echo "it worked"fi [root@eyu sbin]# sh data.sh data.sh:行2: data: 未找到命令[root@eyu sbin]# cat data.sh #!/bin/bashif data ##修改后的thenecho echo "it worked"fi 

bash shell中的if语句在if行定义的命令。假如命令的退出状态是0(成功执行),将执行then后面的所有命令,假如命令的退出状态是非0的,那么then后面的命令将不会执行。
($?命令的返回状态) 0 命令成功结束 1 通用未知错误 2 误用shell命令 126 命令不可执行 127 没找到命令 128 无效退出参数 128+x Linux 信号x的严重错误 130 Linux 信号2 的严重错误,即命令通过SIGINT(Ctrl+C)终止 255 退出状态码越界

另一种形式if command;thenconmmandsfi

2、if-then-else语句
那么相应的命名返回状态为非0时,还需要执行少量需求时就需要多一种选择
命令的结构式

if command ;then  commandselse  commandsfi

假如命令的返回状态为非0时,bash shell会移步到脚本的下一条命令。反之就会执行在then部分。

[root@eyu sbin]# cat grep1.sh grep.sh #!/bin/bashuser=nihao ##判断存在的客户if grep $user /etc/passwd;then    echo the files for user $user are:else    echo "the user name $user doesn't exist this system"fi#!/bin/bashuser=root ##判断存在的客户if grep $user /etc/passwd;then    echo the files for user $user are:else    echo "the user name $user doesn't exist this system"fi[root@eyu sbin]# [root@eyu sbin]# sh grep.sh root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologinthe files for user root are:[root@eyu sbin]# sh grep1.sh the user name nihao doesn't exist this system

3、嵌套if语句
有时在脚本代码中需要检查几种情况。if-then-else满足不了时,需要elif。

if command1;then  commandselif command2;then  commandselif command3;then  commandsfi

像这种情况会按循序匹配command1/2/3的执行返回值,第一个返回0时的elif会执行then部分


4、test命令
if语句中除了执行普通的shell命令外,还有一个test命令。
test命令根据退出代码状态,判断条件执行条件为true或者者false。

test的命令格式:test condithoncondition是一系列test命令评估的参数和值。在if-then语句中使用时,命令格式:if test condition;then  commandsfi或者if [ condition ];then  commandsfi方括号里定义了test命令的使用条件。(在括号里括号的开头和结尾必需加一个空格,否则会报错)test命令能够评估一下3类条件:*数值比较*字符串比较*文件比较

4.1数值比较


数值比较.png
[root@eyu sbin]# sh contrast.sh 1 2不相等[root@eyu sbin]# sh contrast.sh 2 2相等[root@eyu sbin]# cat contrast.sh #!/bin/bashif [ $1 -eq $2 ];thenecho 相等elseecho 不相等fi[root@eyu sbin]# 依次类推

在test命令中是不能够传浮点数的,命令中会报错

[root@eyu sbin]# sh folt.sh 3.333folt.sh: 第 4 行:[: 3.333: 期待一元表达式我们不一样[root@eyu sbin]# cat folt.sh #!/bin/basha=`echo "scale=3;10/3" |bc`echo $a if [ $a >= 3 ];thenecho 一样elseecho 我们不一样fi

4.2字符串比较


字符串比较.png
等于判断[root@eyu sbin]# cat str.sh #!/bin/bashif [ $1 = $2 ];thenecho 一样elif [ $1 != $2 ];thenecho 不一样fi[root@eyu sbin]# sh str.sh aa aa一样[root@eyu sbin]# sh str.sh aa bb不一样字符串比较长度是的大于或者小于在shell中要特别注意俩点:*大于和小于肯定要转义,否则shell会解释成重定向符号,将字符串看出文件名*大于和小于顺序于在sort命令中的顺序不同[root@eyu sbin]# sh str.sh thccc大于[root@eyu sbin]# sh str.sh thcc不大于[root@eyu sbin]# cat str.sh #!/bin/basha=thccif [ $1 \> $a ];thenecho 大于 else echo 不大于fi[root@eyu sbin]# sh str.sh bb大于[root@eyu sbin]# sh str.sh bbaaa大于[root@eyu sbin]# sh str.sh bbaaaaaa大于[root@eyu sbin]# cat str.sh #!/bin/basha=thccif [ $1 > $a ];then ##要的结果变成了重定向echo 大于 else echo 不大于fi  

4.3字符串大小和文件比较

字符串比较[root@eyu sbin]# cat len.sh #!/bin/bashif [ -n $1 ];thenecho 长度大于零else echo 空fiif [ -z $1 ];thenecho 空else echo 长度大于零fi[root@eyu sbin]# sh len.sh nihao长度大于零长度大于零[root@eyu sbin]# sh len.sh 长度大于零空文件比较-d file 检查文件能否存在并且是目录-e file 检查文件能否存在-f file 检查问价能否存在并且是一个文件-r file 检查文件能否可读-s file 检查文件能否存在并且不为空-w file 检查文件能否可写-x file 检查文件能否可执行-O file 检查文件能否存在且被当前客户拥有-G file 检查文件能否存在且是当前客户组file1 -nt file2 检查 文件1能否比文件2新file1 -ot file2 检查文件1 能否比文件2旧*案例1 目录对象文件比较[root@eyu sbin]# sh check.sh /etc/passwd不是目录对象存在是文件[root@yu sbin]# cat check.sh #!/bin/bashif [ -d $1 ];thenecho 是目录elseecho 不是目录fiif [ -e $1 ];thenecho 对象存在elseecho 对象不存在fiif [ -f $1 ];thenecho 是文件elseecho 不是文件fi  *案例2 文件属组能否可读比较[root@eyu sbin]# sh check1.sh /etc/resolv.conf文件存在文件有可读权限文件是当前的客户组[root@eyu sbin]# cat check1.sh #!/bin/bashif [ -f $1 ];thenecho 文件存在    if [ -r $1 ];then echo 文件有可读权限;else null;fi    if [ -G $1 ];then echo 文件是当前的客户组;else null;fielseecho 文件不存在fi[root@eyu sbin]# ll -a /etc/resolv.conf-rw-r--r--. 1 root root 53 10月  4 17:18 /etc/resolv.conf*案例3 文件或者文件夹能否有数据查询[root@eyu sbin]# sh null.sh 文件或者文件夹有数据[root@eyu sbin]# sh null.sh kong.txt null[root@eyu sbin]# cat null.sh #!/bin/bashif [ -s $1 ];thenecho 文件或者文件夹有数据elseecho nullfi*案例4 文件能否可写可执行[root@eyu sbin]# sh wr.sh /etc/passwd可写null[root@eyu sbin]# chmod u+x wr.sh [root@eyu sbin]# ./wr.sh wr.sh 可写可执行[root@eyu sbin]# ll -a wr.sh -rwxr--r--. 1 root root 118 10月  5 00:17 wr.sh[root@eyu sbin]# cat wr.sh #!/bin/bashif [ -w $1 ];thenecho 可写    if [ -x $1 ];then echo 可执行;else echo null;fielse echo 不可写fi

5、复合条件检查
在if-then中使用布尔逻辑来合并检查条件:

 and*[ condition1 ]  && [ condition2 ] or*[ condition1 ]  || [ condition2 ] *案例[root@eyu sbin]# ./wr.sh wr.sh 可写可执行[root@eyu sbin]# ./wr.sh /etc/passwd可以或者可执行或者都没有[root@eyu sbin]# cat wr.sh if [ -w $1 ] && [ -x $1 ];then echo 可写可执行elseecho 可以或者可执行或者都没有fi [root@eyu sbin]# 

6、if-then的高级特征

*双圆括号表示数学表达数*双方括号表示高级字符串解决函数
6.1双圆括号命令符号val++ 后自增、val--后自减、++val前自增、--val前自减、!逻辑否定、~取反、**取幂、<< 逐为左移、>> 逐位右移、&布尔值与、|布尔值或者、&&逻辑与、||逻辑或者*案例[root@eyu sbin]# sh towbrackets.sh 30900[root@eyu sbin]# sh towbrackets.sh 1小于[root@eyu sbin]# cat towbrackets.sh #!/bin/bashif (( $1 ** 2 > 90));then(( a = $1 ** 2 ))echo $aelse echo 小于fi6.2使用双方括号格式[[ expression ]]双括号里用的expression使用在test命令中,给test命令带来了一个功能叫:模式匹配在模式匹配中可以定义字符串匹配的正则表达式*案例[root@hzy sbin]# sh user.sh 是[root@hzy sbin]# cat user.sh #!/bin/bashif [[ $USER == ro* ]];thenecho 是elseecho 不是fi

7、case命令
语法:

case variable in pattern 1 | pattern2) commands;;pattern 3) commands;;*) commands;;esac

在一组数据中找固定的值,这种情况就需要屡次调用if-then-else语句,如下所示:

[root@hzy sbin]# sh userif.sh 当前客户是root[root@hzy sbin]# cat userif.sh #!/bin/bashif [ $USER == root ];thenecho 当前客户是$USER  elif [ $USER == bob ];thenecho 当前客户是$USERelif [ $USER == boc ];thenecho 当前客户是$USERelseecho 没有这个客户fi 

像这种屡次调用elif的语句可以用case命令简写:

[root@hzy sbin]# sh userif.sh root, bob, boc是列表中的root[root@hzy sbin]# cat userif.sh #!/bin/bashlist="root, bob, boc"echo $listcase $USER inroot | bob | boc)echo 是列表中的$USER;;*)echo 没有列表中的客户esac[root@hzy sbin]# 

8、for命令
表达式格式是:

for var in listdo   commandsdone

这个命令是一种常见的编程命令。通常用来重复一系列命令,直到满足一个特定的值或者条件迭代结束。

8.1 读取列表中的值
for命令的最基本的使用方法是通过for命令中定义的一列值来迭代

[root@hzy sbin]# sh list.sh next start nihaonext start wonext start shinext start shei[root@hzy sbin]# cat list.sh #!/bin/bashfor i in nihao wo shi shei doecho next start $idone [root@hzy sbin]# 

8.2 读取列表中的复杂值
I don't know if this'll work

[root@hzy sbin]# sh list.sh next start:Inext start:dont know if thisllnext start:work[root@hzy sbin]# cat list.sh #!/bin/bashfor i in I don't know if this'll work  doecho next start:$idone 突然发现在列表中出现了'号,而后出来的值顺序发生了变化。像这种情况有俩种处理办法:*使用转义字符(反斜杠)来转义单引号;*使用双引号来定义使用单引号的值。案例[root@hzy sbin]# sh list.sh next start:Inext start:dont know if thisllnext start:work--------------------------------------------------------------------next start:Inext start:don'tnext start:knownext start:ifnext start:this'llnext start:work-------------------------------------------------------------------next start:I don't know if this'll work-------------------------------------------------------------------next start:Inext start: don'tnext start:knownext start:ifnext start:this'llnext start:work[root@hzy sbin]# cat list.sh #!/bin/bashfor i in I don't know if this'll work  doecho next start:$idone echo --------------------------------------------------------------------for i in I don\'t know if this\'ll work ##1  doecho next start:$idone echo -------------------------------------------------------------------for i in "I don't know if this'll work"  ##2doecho next start:$idone echo -------------------------------------------------------------------for i in "I" " don't" "know" "if" "this'll" "work"  ##2doecho next start:$idone 

8.3 从变量读取列表

[root@hzy sbin]# sh list1.sh Content viewed root;Content viewed bob;Content viewed gc;Content viewed goc;Content viewed admin;Content viewed tccapache;[root@hzy sbin]# cat list1.sh #!/bin/bashlist="root bob gc goc admin tcc"list=$list"apache"for i in $list do  echo "Content viewed $i;"done

8.4 读取命令中的值

[root@hzy sbin]# sh list2.sh Content viewed on user roo;Content viewed on user apache;Content viewed on user pas;Content viewed on user bob;Content viewed on user hz;Content viewed on user gouzhi;Content viewed on user wanghao;[root@hzy sbin]# cat list2.sh #!/bin/bashfor i in `cat user.txt`doecho "Content viewed on user $i;"done[root@hzy sbin]# cat user.txt rooapachepasbobhzgouzhiwanghao

8.5 改变shell的字段分割符
在默认情况下,bash shell 的默认分割符是:

*空格;*制表符;*换行符。

修改默认环境变量IFS的值,限制bash shell 看作是字段分割字符的字符。

案例1[root@hzy sbin]# sh list3.sh list this is user roolist this is user apachelist this is user paslist this is user boblist this is user hzlist this is user gouzhilist this is user wanghaolist this is user rooapachepasbobhzgouzhiwanghaolist this is user rooapachepasbobhzgouzhiwanghao[root@hzy sbin]# cat user.txt rooapachepasbobhzgouzhiwanghao因为user.txt文件的格式使用的是换行符,所以只有限定IFS为换行符时执行了遍历。案例2[root@hzy sbin]# sh test.sh rootx00root/root/bin/bashbinx11bin/bin/sbin/nologin[root@hzy sbin]# cat test.sh #!/bin/bashIFS=$'\n':  #限定多个分割符for i in `cat /etc/passwd |head -n 2`do echo $i done 

8.6 使用通配符读取目录
文件通配是生成与指定通配符匹配的文件或者路径名的过程

[root@hzy sbin]# cat wildcard.sh #!/bin/bashfor i in /var/log/*  do    if [ -d $i ];then        echo 输出目录$i    elif [ -f $i ];then        echo 输出文件$i    fidone[root@hzy sbin]# sh wildcard.sh 输出目录/var/log/anaconda输出目录/var/log/audit输出文件/var/log/boot.log输出文件/var/log/boot.log-20180626输出文件/var/log/boot.log-20180627输出文件/var/log/boot.log-20181004输出文件/var/log/boot.log-20181006输出文件/var/log/btmp输出文件/var/log/btmp-20181003输出目录/var/log/chrony...

9.C式的for命令
9.1 C语言中的for命令

for (i = 0 ; i < 10 ; i ++){printf ("The next number is %d\n" , i);}一个简单的自增迭代式[root@hzy sbin]# sh for.sh The next number is 0The next number is 1The next number is 2The next number is 3The next number is 4The next number is 5The next number is 6The next number is 7The next number is 8The next number is 9The next number is 10The next number is 11The next number is 12The next number is 13The next number is 14The next number is 15The next number is 16The next number is 17The next number is 18The next number is 19The next number is 20[root@hzy sbin]# cat for.sh #!/bin/bashfor (( i=0; i <=20; i++ ))do echo "The next number is $i"done 

9.2 使用多个变量
c式的for命令同样可以使用多个变量迭代:

[root@hzy sbin]# sh for.sh 1 - 102 - 93 - 84 - 75 - 66 - 57 - 48 - 39 - 210 - 1[root@hzy sbin]# cat for.sh #!/bin/bashfor (( i=1, b=10; i <= 10; i++, b-- ))do     echo "$i - $b"done 

10、while 命令
while命令的格式:

while test commanddo   other commanddone案例[root@hzy sbin]# sh while.sh 10987654321[root@hzy sbin]# cat while.sh #!/bin/bashnumber=10while [ $number -gt 0 ]do     echo $number    number=$[ $number - 1 ]done[root@hzy sbin]# 

10.1 使用多个条测试命令

[root@hzy sbin]# sh while.sh 1098765[root@hzy sbin]# cat while.sh #!/bin/bashnumber=10while [ $number -gt 0 ] ##设置大于0    [ $number -ge 5 ] ##设置大于等于5do     echo $number    number=$[ $number - 1 ]done*while命令允许在while语句行定义多条test命令。只有最后一条测试命令的退出状态是用来决定循环是如何中止的。

11、until命令
这个命令测试的结果和while相反,只测试退出状态为非0的情况,退出状态为非0,循环中止。
until的命令格式:

until test commandsdo  other commandsdone案例[root@hzy sbin]# sh -x until.sh + a=100+ '[' 100 -eq 0 ']'+ echo 100100+ a=75+ '[' 75 -eq 0 ']'+ echo 7575+ a=50+ '[' 50 -eq 0 ']'+ echo 5050+ a=25+ '[' 25 -eq 0 ']'+ echo 2525+ a=0+ '[' 0 -eq 0 ']'[root@hzy sbin]# cat until.sh #!/bin/basha=100until [ $a -eq 0 ]doecho $aa=$[ $a - 25 ]done依次判断直到a=0时退出循环

12、嵌套循环

while和for的嵌套[root@hzy sbin]# sh while-for.sh Input 10input sum的值10input sum的值11Input 9input sum的值9input sum的值10Input 8input sum的值8input sum的值9Input 7input sum的值7input sum的值8Input 6input sum的值6...[root@hzy sbin]# cat while-for.sh #!/bin/basha=10while [ $a -ge 0 ]do echo "Input $a"     for (( i = 0; $i < 2; i++ ))        do            sum=$[ $a + $i ]            echo "input sum的值$sum"        donea=$[ $a - 1]done 

13、文件数据的循环
这里需要结合
*使用嵌套循环 *更改环境变量IFS

...adm:x:3:4:adm:/var/adm:/sbi -value-key: admvalue-key: xvalue-key: 3value-key: 4value-key: admvalue-key: /var/admvalue-key: /sbiValues in / -value-key: /Values in ologi -value-key: ologi[root@hzy sbin]# cat file.sh #!/bin/bash#IFS.OLD=$IFSIFS='\n'for i in `cat /etc/passwd |head -n 4`do    echo "Values in $i -"    IFS=:    for z in $i    do        echo "value-key: $z"    done#IFS=$IFS.OLDdone

14、循环的控制
循环不肯定执行完,对于循环的控制需要用到俩个命令:
break命令: continue命令。
14.1 break命令
这个命令是跳出循环

[root@hzy sbin]# sh break.sh ---------------5------------[root@hzy sbin]# cat break.sh #!/bin/bashfor i in `seq 1 10`do     if [ $i -eq 5 ];then         break       fidone echo ---------------$i------------ ##不加break,正常情况这个$i会输出1-10这个命令同样适用于while和until循环

14.2 continue命令
跳出循环后继续执行

[root@hzy sbin]# sh continue.sh ----------------------1-----------------------------------------2-----------------------------------------3-----------------------------------------4-----------------------------------------6-----------------------------------------7-----------------------------------------8-----------------------------------------9-----------------------------------------11-----------------------------------------12-----------------------------------------13-----------------------------------------14-----------------------------------------15-----------------------------------------16-----------------------------------------17-----------------------------------------18-----------------------------------------19-----------------------------------------20-------------------[root@hzy sbin]# cat continue.sh #!/bin/bashfor i in `seq 1 20`do     case $i in     5 )        continue     ;;     10)        continue     ;;    esacecho ----------------------$i-------------------##这里只是跳过了5和10done  

15、解决循环的输出
最后,可以在shell脚本中使用管道或者重定向的方式输出结果。通过在done命令的末尾增加解决命令实现

*重定向[root@hzy sbin]# cat output.txt 输出文件--/home/all-in-one输出目录--/home/hzy输出目录--/home/kolla-ansible输出文件--/home/multinode[root@hzy sbin]# cat yy.sh #!/bin/bashfor i in /home/* doif [ -d $i ];then    echo "输出目录--$i"    elif [ -f $i ];then    echo "输出文件--$i"fidone > output.txt*管道符号[root@hzy sbin]# sh sort.sh 123-----------------aFASDF-----------------aff-----------------asA-----------------fsdf222-----------------s2234-----------------[root@hzy sbin]# cat sort.sh #!/bin/bashfor i in 123 aff s2234 asA aFASDF fsdf222doecho $i-----------------done | sort

END

  • 全部评论(0)
最新发布的资讯信息
【系统环境|服务器应用】前台开发入门到实战:HTML5语义化元素你真的用的正确吗?(2019-08-22 04:16)
【系统环境|服务器应用】Vue仿微信app页面跳转动画(2019-08-22 04:16)
【系统环境|服务器应用】webstorm使用快捷键快速修正单个文件的style(2019-08-22 04:16)
【系统环境|服务器应用】程序员从学生到阿里经历的5次蜕变:海阔凭鱼跃,天高任鸟飞(2019-08-22 04:16)
【系统环境|服务器应用】var、let、const的区别(2019-08-22 04:16)
【系统环境|服务器应用】mini-ui加载框Indicator 被遮挡问题(2019-08-22 04:15)
【系统环境|服务器应用】【对讲机的那点事】玩对讲机,对于对讲机的亚音你理解吗?(2019-08-22 04:15)
【系统环境|服务器应用】前台中高级面试,内功心法(上)(2019-08-22 04:15)
【系统环境|服务器应用】17、改进轮播图之功能封装(2019-08-22 04:15)
【系统环境|服务器应用】第10题- 你不知道的delete操作符(2019-08-22 04:15)
手机二维码手机访问领取大礼包
返回顶部