前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux22-条件语句

linux22-条件语句

作者头像
北野茶缸子
发布2022-07-07 14:39:06
1.3K0
发布2022-07-07 14:39:06
举报
文章被收录于专栏:北野茶缸子的专栏
  • Date : [[2022-05-02_Mon]]
  • 微信公众号 : 北野茶缸子
  • Tags : #linux/index/01

前言

来学习一下shell 中的条件语句吧。

1-if条件句

shell 中的if 与其他编程语言有所不同。它默认下的if 后的对象为一个命令(command),而非通常的条件(condition)。

代码语言:javascript
复制
if command1
then  
  command2
fi

且结尾处,需要用fi 标记条件语句的结束。

因此,shell 中的if,则是根据这个命令结束后返回的状态码,来决定是否运行后面的语句。

1.1-退出码

每个命令都使用退出状态码(exit status) 来告诉shell 该命令已经完成。

shell 中,使用$? 来作为变量记录每次命令执行后返回的退出状态码。

代码语言:javascript
复制
$ ls
...
$ echo $?
0

$ 法克鱿
法克鱿: command not found  
$ echo $?
127

这里的0 表示命令成功,而127 则表示该命令没有被找到。ps:其实非常类似网页的http error 404 或是各种蓝屏代码,不同代码对应不同的信息。

1.2-基本if语句

基本if 语句的完整结构如下:

代码语言:javascript
复制
if command1
then  
  command2
elif command3
then 
  command4
else command5
  if command6
  then
    command7
  fi
fi
  • 通常if条件句的执行顺序为优先执行if 中的命令,若该命令的退出码为0(成功结束),则执行紧跟if 的then 中的命令。若返回非零退出码,则会执行else部分。
  • elif则相当于 else + if + then,若elif 后命令的退出码为0,则会继续执行elif 后面的语句。
  • 但需要注意的是,elif 实际相当于一个新的if语句,因此elif后面的then与else是相对于elif的退出码来执行的:为0则执行then,非零则执行else
  • 有时候在执行了一次条件之后,还可以使用嵌套if,检查更多的条件。需要注意的是,每一次调用if,都需要在当前的结尾处使用fi,声明if-then语句的结束。

需要注意的是,默认的if 语句,command 中的命令也是会被执行的:

代码语言:javascript
复制
❯ if ls > /dev/null; then pwd; fi
/Users/appe/Desktop
❯ if echo '666'; then pwd; fi
666
/Users/appe/Desktop

1.3-条件if语句

shell 中,也提供了可以让if 语句转变为条件(condition)结构的语法。称为 test 条件命令。test 条件命令有两种语法:

代码语言:javascript
复制
if [ condition2 ]
if test condition1

如果这个condition 成立,则会返回退出状态码0、

⚠️注意:中括号与条件之间需要间隔一个空格。

代码语言:javascript
复制
❯ if test 'asd'>'as'; then echo 'bigger'; fi
bigger
❯ if ['asd'>'as']; then echo 'bigger'; fi
zsh: bad pattern: [asd
❯ if [ 'asd'>'as' ]; then echo 'bigger'; fi
bigger

如果是比较数字大小:

代码语言:javascript
复制
❯ if [ 32\>66 ]; then echo 'bigger'; fi
bigger

有点奇怪,对吧。

2-三种if条件语句

shell 提供了三种类型的比较,且三者语法也存在不同。三类条件的判断:

  • 数值比较
  • 字符串比较
  • 文件比较

2.1-数值比较

如果你学习过perl 的话,对此可能会深有体会:

代码语言:javascript
复制
$ cat test.perl 
#!/usr/bin/perl

if('as' gt 'a'){
 print "hello!\n";
}

$ perl test.perl
hello!

但shell 不同于perl,它们二者的数值与字符串的符号正好相反。

在shell 中,数值比较操作符为:

代码语言:javascript
复制
lt # less than
gt 
eq # equal to 
le # less or equal
ge
ne # not equal
cmp # compare return 1,0,-1

一个判断数值大小的命令:

代码语言:javascript
复制
a=666
b=6666
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi
a 小于 b

需要注意的是,bash shell 只能处理整数,也即如果语句中出现浮点值,则shell 会报错。

代码语言:javascript
复制
if [ 54.22 -gt 44 ]
then echo -e "hello!"
fi

line 3: [: 54.22: integer expression expected

2.2-字符串比较

需要注意的是,test 命令的数值比较与字符串比较使用不同的比较符号进行比较。因此在使用时需要注意,如果使用了字符串比较符号对数值进行比较,则shell 会将数字当作字符串值进行运算,会对结果造成影响。

因此,在开头的案例中:

代码语言:javascript
复制
❯ if [ 32\>66 ]; then echo 'bigger'; fi
bigger

这里使用转义符号,因为> 与 < 在shell 中有重定向之意,因此在实际比较中需要使用转义符\。

字符串比较语法如下:

代码语言:javascript
复制
str1 = str2 # 相等
str1 != str2
str1 < str2 # 小于
str1 > str2
-n str1 # 检查str1 长度是否非0
-z str1 # 检查str1 长度是否为0

且规则如下:

  • 较长的字符串小于较短的字符串;
  • 大写字母小于小写字母。

因为比较测试采用的是ASCII 顺序,因此大写字母出现在小写字母之前:

此外,-n与-z 选项非常重要,可以用来在操作数值或字符比较前用于确定其是否为空。

但根据我的测试:

代码语言:javascript
复制
❯ if test -z asd;then echo 'zero'; fi
❯ if test -z ;then echo 'zero'; fi
zero

似乎用于比较的语法无法进行比较:

代码语言:javascript
复制
❯ if test asdasds\>das ;then echo 'zero'; fi
zero
❯ if test asdasds\<das ;then echo 'zero'; fi
zero

你们知道原因吗?

反正我是有点摸不着头脑,这种条件测试语法,我并不是很喜欢。

2.3-文件比较

文件比较是比较测试中最丰富的类型:

代码语言:javascript
复制
-d file # 检查file 是否为一个目录
-e file # 检查file 是否存在
-f file # 是否为文件
-r file # 是否可读
-s file # 是否非空
-w file # 是否可写
-x file # 是否可执行
-O file # 是否属于当前用户
-G file # 默认组是否与当前用户相同
file1 -nt file2 # 判断文件哪个更新
file1 -ot file2 # 判断文件哪个更旧
! # 条件前面加!表示取反
代码语言:javascript
复制
mkdir test_{1..5}
❯ if test test_1 -ot test_5; then echo older; fi
older

3-复合条件测试

shell 提供了两种布尔运算符实现复合条件测试:

代码语言:javascript
复制
[ condition1 ] && [ condition2 ] # AND,需要满足两个条件才返回0
[ condition3 ] || [ condition4 ] # OR,满足其中之一即可返回0
代码语言:javascript
复制
❯ if [ test_1 -ot test_5 ] || [ 5 -gt 10 ]; then echo older; fi
older

4-高级条件表达式

4.1-高级数学表达式

可以使用双括号,实现高级的数学表达式。同样地,需要在括号与语句之间,保留空格。ps:这也是我个人喜欢用的。

这样的表达使得数学赋值与比较变得更加灵活。比如单方括号的条件测试,是无法执行多命令与数学运算的。

代码语言:javascript
复制
❯ if [ 54 ** 2 -gt 44 ];then echo -e "hello";fi
if (( 54 ** 2 > 44 ));then echo -e "hello";fi
if (( 54.3 > 54 ));then echo -e "hello";fi
zsh: condition expected: 54
hello
hello

以下优点:

  • 数学运行和比较同时执行;
  • 直接使用数学符号比较,且无需转义;
  • 可以对浮点数进行比较。

还有以下的特别符号:

代码语言:javascript
复制
val++  # 后增
val--
++val # 先增
--val 
! # 逻辑求反
~ # 位求反
** # 幂
<< # 左位移
>>
& # 位布尔和
| # 位布尔或
&& # 逻辑和
|| # 逻辑或

其中需要注意的,就是这个后增与先增,在如python 中包含这类特性的语言里,同样存在这个知识点:

代码语言:javascript
复制
$ cat test2
#!/bin/bash

var1=1
var2=1
if (( ++var1 > var2++ ))
then echo -e "hello! And $var1, $var2"
fi
$ test2
hello! And 2, 2

虽然二者都执行同样的运算,且总结果来看,二者都有了一致的结果。但从then 被执行可知,if 语句的退出状态码为0,因此表达式成立。而先增与后增也就在于,先增为在当前语句执行前就进行了增加(if 判断前),而后增则是if 判断完成后再进行增加。因此2>1,也就是条件成立。

另外,在进行先/后 增/减表达时,需要将变量的 $ 去掉:

代码语言:javascript
复制
$ cat test2
#!/bin/bash

var1=1
var2=1
if (( $++var1 > $var2++ ))
then echo -e "hello! And $var1, $var2"
fi
$ test2
/tmp/test/test2: line 5: ((: $++var1 > 1++ : syntax error: operand expected (error token is "$++var1 > 1++ ")

4.2-高级字符串表达式

使用高级字符串表达式,就符合上面的字符串比较的规则了:

代码语言:javascript
复制
❯ if [[ 'asdasds' < 'das' ]] ;then echo 'zero'; fi
zero
❯ if [[ 'asdasds' > 'das' ]] ;then echo 'zero'; fi

规则如下:

  • 较长的字符串小于较短的字符串;
  • 大写字母小于小写字母。

括号中可以定义一些正则表达式来匹配字符串:

代码语言:javascript
复制
❯ [[ sad == s* ]] && echo 'good'
good

5-没有if的条件判断

上面介绍的条件表达式,本质上还是一个命令,只是这个命令是用来进行判断的,其并没有返回值,而其对应的退出码,会传递给if 以进行后续的判断。

比如我们可以利用逻辑运算符,实现简单的if then功能:

代码语言:javascript
复制
&& # 逻辑和
|| # 逻辑或
代码语言:javascript
复制
❯ [[ sad == s* ]] && echo 'good'
good
❯ if [[ sad == s* ]];then echo 'bad'; fi
bad

6-case语句

case 相当于便携版本的if else elif:

代码语言:javascript
复制
❯ for i in a b c;do case $i in
a | b)
        echo 'hello.';;
c)
        echo 'good bye.';;
esac; done
hello.
hello.
good bye.

ps:感觉所有语言中的case,都不是很受欢迎啊。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1-if条件句
    • 1.1-退出码
      • 1.2-基本if语句
        • 1.3-条件if语句
        • 2-三种if条件语句
          • 2.1-数值比较
            • 2.2-字符串比较
              • 2.3-文件比较
              • 3-复合条件测试
              • 4-高级条件表达式
                • 4.1-高级数学表达式
                  • 4.2-高级字符串表达式
                  • 5-没有if的条件判断
                  • 6-case语句
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档