【问题标题】:Bash Script is returning true for both but opposite string testsBash 脚本对两个但相反的字符串测试都返回 true
【发布时间】:2012-12-11 02:49:48
【问题描述】:

在我运行之前输入的脚本

# export CPIC_MAX_CONV=500

下面是test1.script文件

#!/bin/bash

function cpic () {
  var="`export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } '`"
  [[ $var=="" ]] && (echo "Empty String <<")
  [[ $var!="" ]] && (echo "$CPIC_MAX_CONV")
  echo "$var" ;
}

cpic

输出是:

# test1.script  ---- Me running the file

Empty String <<
500
CPIC_MAX_CONV="500"

无论我使用什么“”或''或[或[[,结果都是一样的。上面的脚本找到了CPIC_MAX_CONV 变量。

我在 Linux/CentOS 6.3 上运行它。

想法很简单:查找CPIC_MAX_CONV 是否在环境中定义并返回它的值。如果有一个空白空间,那么系统中当然不存在该变量。

【问题讨论】:

    标签: linux bash ubuntu centos boolean-logic


    【解决方案1】:

    为什么你总是说实话?让我们先在你的终端上玩一点:

    $ [[ hello ]] && echo "True"
    

    你认为输出是什么? (试试看!)还有以下内容?

    $ [[ "" ]] && echo "True"
    

    (试试看!)。

    好吧,看来非空字符串等价于真表达式,空字符串(或未设置的变量)等价于假表达式。

    你做了以下事情:

    [[ $var=="" ]]
    

    和

    [[ $var!="" ]]
    

    所以你给了一个非空字符串,这是真的!

    为了执行测试,你实际上需要在标记之间有空格:

    [[ $var == "" ]]
    

    相反。现在,您的测试最好写成:

    if [[ -z "$var" ]]; then
        echo "Empty String <<"
    else
        echo "$CPIC_MAX_CONV"
    fi
    

    (没有子外壳,只有一个测试)。

    关于您的脚本风格还有很多话要说。没有冒犯,我会说这真的很糟糕:

    • 不要使用反引号!请改用$(...) 构造。因此:

      var="$(export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } ')"
      
    • 不要使用function blah 来定义函数。你的函数应该被定义为:

      cpic () {
          local var="$(export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } ')"
          if [[ -z "$var" ]]; then
              echo "Empty String <<"
          else
              echo "$CPIC_MAX_CONV"
          fi
      }
      

    哦,我使用了local 关键字,因为我猜你不会在函数cpic 之外使用变量var。

    现在,函数cpic 的用途是什么,尤其是您定义变量var 的地方?这很难描述(因为有很多你没有想到的案例)。 (顺便说一句,你的grep 在这里似乎真的没用)。以下是您忽略的几个案例:

    • 导出的变量名为somethingfunnyCPIC_MAX_CONVsomethingevenfunnier
    • 导出的变量在某处包含字符串CPIC_MAX_CONV,例如,

      export a_cool_variable="I want to screw up Randhawa's script and just for that, let's write CPIC_MAX_CONV somewhere here"
      

    好的,我不想描述你的行在做什么,但我猜你的目的是知道变量CPIC_MAX_CONV 是否已设置并标记为导出,对吗?在这种情况下,你最好这样做:

    cpic () {
        if declare -x | grep -q '^declare -x CPIC_MAX_CONV='; then
            echo "Empty String <<"
        else
            echo "$CPIC_MAX_CONV"
        fi
    }
    

    它将更高效,更健壮。

    哦,我现在正在阅读您帖子的结尾。如果您只想判断变量 CPIC_MAX_CONV 是否已设置(设置为一些非空值 - 似乎您不在乎它是否标记为导出,如果我错了请纠正我),它甚至更简单(并且效率会高得多):

    cpic () {
        if [[ "$CPIC_MAX_CONV" ]]; then
            echo "Empty String <<"
        else
            echo "$CPIC_MAX_CONV"
        fi
    }
    

    也可以!

    【讨论】:

    • 我认为if 是一个命令。接下来的所有内容都是由空格分隔的参数,就像任何其他命令一样。
    • @BarryBrown 准确地说,if 是一个关键字:type if 返回if is a shell keyword。
    • 为什么不使用function关键字?
    【解决方案2】:

    您真的关心 CPIC_MAX_CONV 是否是一个环境变量而不是“它是一个可能是环境变量的变量”吗?最有可能的是,您不会,尤其是因为如果它是一个变量而不是环境变量,那么您运行的任何脚本都不会看到该值(但如果您坚持使用别名和函数,那么它可能很重要,但仍然可能不会)。

    然后,您似乎正在尝试测试 CPIC_MAX_CONV 是否设置为非空值。有多种简单的方法可以做到这一点 - 然后就是您尝试过的方法。

    : ${CPIC_MAX_CONV:=500}
    

    这可确保将 CPIC_MAX_CONV 设置为非空值;如果以前没有设置值,它使用 500。 :(冒号)命令评估其参数并报告成功。如果您想使用export CPIC_MAX_CONV,您可以安排在创建变量后将其导出。

    如果你必须设置变量(没有合适的默认值),那么你使用:

    : ${CPIC_MAX_CONV:?}
    

    或

    : ${CPIC_MAX_CONV:?'The CPIC_MAX_CONV variable is not set but must be set'}
    

    不同之处在于您可以使用默认消息('CPIC_MAX_CONV: parameter null or not set')或指定您自己的消息。

    如果您只打算使用该值一次,您可以在命令中进行“即时”替换:

    cpic_command -c ${CPIC_MAX_CONV:-500} ...
    

    如果变量不存在,这不会创建变量,这与 := 表示法不同。

    在所有这些符号中,我一直使用冒号作为操作的一部分。强制执行“null or not set”;您可以省略冒号,但这允许空字符串作为有效值,这可能不是您想要的。请注意,仅由空格组成的字符串是“非空的”;如果你需要验证你有一个非空字符串,你必须更加努力。


    我不是在剖析您对[[ 命令的滥用; gniourf_gniourf 提供了一个出色的 deconstruction,但忽略了更简单的符号来完成似乎是这项工作。

    【讨论】:

      【解决方案3】:

      你的条件需要空格。

      #!/bin/bash
      
      function cpic () {
          var="`export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } '`"
          [[ $var == "" ]] && (echo "Empty String <<")
          [[ $var != "" ]] && (echo "$CPIC_MAX_CONV")
          echo "$var" ;
      }
      
      cpic
      

      【讨论】:

      • 我不确定您的回答是否会为其他回答添加任何有趣的内容。此外,您留下了 OP 的所有错误(使用反引号、使用无用的子shell、无用的 grep、不推荐使用 function 关键字,也许不是实现他想要实现的最佳算法)。 -1.
      • 无意冒犯,但我回答了问题的主题。 OP 并没有在这里询问最佳编码实践。
      • 没有冒犯。然后,至少解释为什么提问者会得到这个相当混乱的结果。
      【解决方案4】:

      试试这个:

      #!/bin/bash
      function cpic () {    
        var="`export | grep -i "CPIC_MAX_CONV"`"
        [ "$var" = "" ] && (echo "Empty String <<")
        [ "$var" != "" ] && echo "$CPIC_MAX_CONV"
      }  
      cpic
      

      【讨论】:

      • 回答问题但不提供任何新信息有什么意义?
      猜你喜欢
      • 1970-01-01
      • 2017-03-16
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多