zoukankan      html  css  js  c++  java
  • shell中的逻辑运算/布尔运算/短路与/短路或

      参考:http://www.zsythink.net/archives/1154

      

      在了解shell中的逻辑运算之前,我们先回顾一下逻辑运算的概念,如下概念引用自"互动百科"。

      什么是逻辑运算 ? 逻辑运算又称布尔运算,逻辑运算用来判断一件事情是"对"的还是"错"的,或者说是"成立"还是"不成立",判断的结果是二值的,即没有"可能是"或者"可能不是",这个"可能"的用法是一个模糊概念,在计算机里面进行的是二进制运算,逻辑判断的结果只有二个值,称这二个值为"逻辑值"("True"或"False"),用数的符号表示就是"1"和"0"。其中"1"表示该逻辑运算的结果是"成立"的,如果一个逻辑运算式的结果为"0",那么这个逻辑运算式表达的内容"不成立"。 

      上述文字引用自 互动百科-逻辑运算

       逻辑运算中,最常用的无非就是 "与"、"或" 、"非",我们先聊聊最容易理解的"非"。

      用两句话概述逻辑运算中的"非":

      非真即假

      非假即真

       shell中,"非"的逻辑运算符为 "!" ,那么,用逻辑运算公式表示上面的两句话,如下

      ! true = false

      ! false = true

       "非"是比较容易理解的,在shell中,"与"和"或"有两种表达方式。

      在shell中,"与"的运算符为"-a",同时,"与"的逻辑运算符也可以用"&&"表示。

      在shell中,"或"的运算符为"-o",同时,"或"的逻辑运算符也可以用"||"表示。

      我们先聊聊"与",我们都知道,当进行与运算时,运算双方必须同时为真,结果才为真,那么用公式表示如下。

      true -a true = true

      true -a false = false

      false -a true = false

      false -a false = false

       在上文中已经提到过,"与"还可以用"&&"表示,但是"&&"与"-a"有所不同,"&&"有短路功能,也可以称为"短路与","&&"与"-a"不仅功能上略有区别,在使用方法上也有不同之处,我们先看看它们在使用方法上有何不同之处。

    当使用"&&"或者"-a"作为条件判断的运算符时,它们的语法略有区别,示例如下:

    [root@node1 shell_learn]# if [ 10 -gt 5 -a 10 -gt 9 ];then echo "true";fi
    true
    [root@node1 shell_learn]# if [[ 10 -gt 5 && 10 -gt 9 ]];then echo "true";fi
    true
    [root@node1 shell_learn]# if [ 10 -gt 5 ] && [ 10 -gt 9 ];then echo "true";fi
    true
    [root@node1 shell_learn]# if [[ 10 -gt 5 -a 10 -gt 9 ]];then echo "true";fi
    -bash: 条件表达式中有语法错误
    -bash: `-a' 附近有语法错误
    [root@node1 shell_learn]# if [ 10 -gt 5 && 10 -gt 9 ];then echo "true";fi
    -bash: [: 缺少 `]'
    [root@node1 shell_learn]# 
    

       从上图可以看出,当使用"&&"或者"-a"作为条件判断的运算符时,"-a"只能用"单大括号"括起,"&&"只能用"双大括号"括起,如果使用"双大括号"括起"-a"或者使用"单大括号"括起"&&",则都会出现语法错误。"&&"除了能用"双大括号"括起,还可以使用"&&"将两个"单括号括起的条件"连接在一起,效果是相同的。

      从上述描述中,我想我已经说明白了"&&"与"-a"在语法上的不同,现在我们再说说"&&"的短路功能。

      在shell命令行中,每一个命令执行以后,都会返回一个状态值,这个状态值如果为0,则表示命令执行成功,即命令执行状态为true,如果这个状态值为非0值,则表示命令执行的状态为false,通过echo $?可以查看命令执行的状态值,示例如下。

    [root@node1 shell_learn]# cd
    [root@node1 ~]# echo $?
    0
    [root@node1 ~]# cd jkdsahfk
    -bash: cd: jkdsahfk: 没有那个文件或目录
    [root@node1 ~]# echo $?
    1
    [root@node1 ~]# 
    

       从上图中可以看到,第一条命令执行成功了,而第二条命令执行失败了,即第一条命令的执行状态返回值为true,第二条命令的执行状态返回值为false,其实,我们可以利用命令的状态返回值以及"&&"的短路特性实现某种功能,比如,cmd1 && cmd2,这个公式表示如果cmd1命令执行成功,则执行cmd2命令,什么意思呢?我们来看一个示例,如下。

    [root@node1 ~]# cd / && echo "cd root dir success"
    cd root dir success
    [root@node1 /]# cd /asd && echo "cd root dir success"
    -bash: cd: /asd: 没有那个文件或目录
    [root@node1 /]# 
    

       从上图示例中,可以看出,当"&&"之前的命令执行成功时,则执行"&&"之后的命令,当"&&"之前的命令执行失败时,"&&"之后的命令则不会被执行

      这就是"&&"所谓的短路功能,即如果cmd1的执行结果为true,则必须要执行cmd2,如果cmd1的执行结果为false,cmd2则不会被执行,为什么会出现这种情况呢?我们之前说过,当进行与运算时,运算双方必须同时为真,结果才为真,所以,即使cmd1的执行结果为真,也必须得出cmd2的执行结果后,才能判断出最终进行"与运算"以后的结果是否为真,也就是说,如果cmd1执行结果为真,cmd2执行结果为假,那么true && false 结果为false,如果cmd1执行结果为真,cmd2执行结果也为真,那么true && true 结果为true,所以,cmd1的结果为真并不能决定最终进行"与运算"以后的结果是否为真,所以cmd2必须执行,而如果cmd1的执行结果为假,那么不管cmd2的执行结果为真或是为假,最终进行"与运算"以后得出的结果肯定为假,所以当cmd1执行失败时,cmd2不会被执行。

      

      聊完了"与",我们再聊聊"或",我们也知道,当进行或运算时,运算双方只要有一个为真,结果即为真,那么用公式表示如下。

      true -o true = true

      true -o false = true

      false -o true = true

      false -o false = false

      同样,在shell中,"-o"表示或,"||"也表示或,但是它们有所不同,之前已经说明了"&&"与"-a"的不同之处,聪明如你一定已经想到,"||"和"-o"的不同之处就是"||"有短路功能,而且它们作为条件判断的运算符时,语法不同,示例如下。

    [root@node1 ~]# if [ 10 -gt 11 -o 10 -gt 9 ];then echo "true";fi
    true
    [root@node1 ~]# if [[ 10 -gt 11 || 10 -gt 9 ]];then echo "true";fi
    true
    [root@node1 ~]# if [ 10 -gt 11 || 10 -gt 9 ];then echo "true";fi
    -bash: [: 缺少 `]'
    -bash: 10: 未找到命令
    [root@node1 ~]# if [[ 10 -gt 11 -o 10 -gt 9 ]];then echo "true";fi
    -bash: 条件表达式中有语法错误
    -bash: `-o' 附近有语法错误
    [root@node1 ~]# if [ 10 -gt 11 ] || [ 10 -gt 9 ];then echo "true";fi
    true
    

       对比之前"&&"的使用方法,就更容易理解了,此处不再赘述,我们主要聊聊"短路或"的用法。因为已经说明了"短路与"的用法,"短路或"就好理解了,我们先回顾一下"短路与"。

       上图中就利用了"&&"的短路特性,即如果cmd1的执行结果为true,则必须要执行cmd2,如果cmd1的执行结果为false,cmd2则不会被执行。那么,我们把上图中的"短路与"改为"短路或",如下图所示

    [root@node1 /]# cd / || echo "cd root dir success"
    

       从上图可以发现,cmd1执行成功后,cmd2并没有被执行,那么此处,我们故意让cmd1执行失败,看看cmd2会不会被执行。

    [root@node1 /]# cd /dasd || echo "cd root dir success"
    -bash: cd: /dasd: 没有那个文件或目录
    cd root dir success
    [root@node1 /]# 
    

       从上图可以看出,当cmd1执行失败时,cmd2则会被执行,这就是"短路或"的特性。

      "||"所谓的短路功能,即如果cmd1的执行结果为false,则必须要执行cmd2,如果cmd1的执行结果为true,cmd2则不会被执行,之所以会这样,是因为在进行"或运算"时,运算双方只要有一个为真,"或运算"之后肯定为真,所以只要cmd1的执行结果为真,那么cmd2就不会再被执行了,因为不管cmd2的执行结果为真或为假,或运算的结果肯定为真,但是,如果cmd1的执行结果为假,那么cmd2则必须被执行,因为如果此时cmd2的执行结果也为假,那么或运算的结果为假,如果cmd2的执行结果为真,则或运算的执行结果为真,此处对比"短路与"的解释更容易理解。

      那么,"短路与"和"短路或"已经解释完毕,我们似乎已经明白了它们的用法,但是,我们能不能结合它们一起使用呢,必须能啊,示例语法如下。

    cmd1 && cmd2 || cmd3
    

       那么,上述语法是什么意思呢?

      上述语法表示,表示如果cmd1执行成功,则执行cmd2,如果cmd1执行失败,则不执行cmd2,而是执行cmd3。

      这可能与我们"一厢情愿"的理解不太一样,为什么会出现上述情况呢,我们来详细解释一下。

      首先cmd1执行,如果cmd1执行状态为真,因为&&的缘故,所以cmd2必须执行,因为有&&的情况下是两个条件同时为真,最终结果才能为真,cmd1执行状态为真的情况下,cmd2的状态决定了最终的结果是不是真,如果cmd2的执行状态也为真 ,那么  (cmd1 && cmd2)这个整体就是真,又因为||的关系,当(cmd1 && cmd2)这个整体就是真的时候 ,cmd3就不用执行了,因为|| 代表只要有一个条件为真,最终的结果就是真,两个条件同时为假,最终的结果才为假, 所以(cmd1 && cmd2)这个整体如果是真,那么结果肯定是真,就不用再考虑cmd3的状态是否为真了,就不用再执行cmd3了。

      但是如果cmd1的执行状态为假,(cmd1 && cmd2)这个整体的状态肯定为假 ,因为&&表示两个条件中只要有一个条件为假,那么结果肯定是假,所以当cmd1为假的时候,cmd2就不会再执行了,因为cmd1为假的时候,cmd2的执行状态并不能影响(cmd1 && cmd2)这个整体的状态,cmd1执行状态为假,(cmd1 && cmd2)肯定是假,(cmd1 && cmd2)是假,可是因为 || 的缘故, cmd3必须执行 ,前面已经说过,||表示两个条件同时为假,最终的结果才是假,因为(cmd1 && cmd2)这个整体是假,所以必须通过cmd3的执行状态,才能判断出最终的结果是不是假,所以cmd3必须执行。

      注意:短路或和短路与的顺序非常重要,它们的前后顺序决定了命令的逻辑。

  • 相关阅读:
    RDIFramework.NET开发实例━表约束条件权限的使用-WinForm
    RDIFramework.NET V2.8版本 ━ 开发实例之产品管理(WinForm)
    RDIFramework.NET ━ Web中打印的各种方案参考-欢迎补充
    RDIFramework.NET 框架兼容各种数据库类型事务使用范例参考
    【干货】再上数据分页控件 ━ 更加灵活,更加实用-提供源码
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增岗位管理-Web部分
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增岗位管理-WinForm部分
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本发布
    Javascript中的apply与call详解
    Javascript定义类(class)的三种方法
  • 原文地址:https://www.cnblogs.com/minseo/p/13717139.html
Copyright © 2011-2022 走看看