【问题标题】:bash command grouping for test results in function函数中测试结果的bash命令分组
【发布时间】:2013-11-12 01:35:49
【问题描述】:

我习惯于使用这样的行来测试变量是否具有非空值(或给出消息和保释):

test $variable || (echo "Value of \$variable cannot be null."; exit 1)

我对在我的脚本中使用函数很陌生,但是我有一个案例,我需要确保传递一个非空值或退出函数。但是,“或”情况的命令分组在函数内部的工作方式不同。我写了这个小测试脚本来演示:

 $ cat -n bubu.sh
 1  #!/bin/bash
 2
 3  read -p "give a value for variable \$foo: " -e -i "bar" foo
 4
 5  function firstfunc {
 6          test $1 || (echo "no value"; return 1)
 7          echo it looks like \"$1\" is  the first value of \$foo
 8          return 0
 9  }
10
11  function secondfunc {
12          test $1 || return 1
13          echo it looks like \"$1\" is the second value of \$foo
14          return 0
15  }
16  echo "first function:"
17  firstfunc $foo
18  echo returned $?
19
20  echo "second function:"
21  secondfunc $foo
22  echo returned $?

而变量有值的情况下的输出是这样的:

$ ./bubu.sh
give a value for variable $foo: bar
first function:
it looks like "bar" is the first value of $foo
returned 0
second function:
it looks like "bar" is the second value of $foo
returned 0

以及没有值的情况下的输出

$ ./bubu.sh
give a value for variable $foo:
first function:
no value
it looks like "" is the first value of $foo
returned 0
second function:
returned 1

在第一个函数中,当没有值时,我得到“or”命令组的第一个命令,“no value”回显,但返回命令被传递,函数的其余部分被执行,down到返回。

为什么命令分组的括号在函数内部表现不同,或者我还缺少什么?

【问题讨论】:

  • Parens 不用于命令分组,它们在子 shell 中运行包含的命令。使用{ ... } 进行命令分组而不创建子shell。

标签: bash function testing parentheses


【解决方案1】:

echo "no value"; return 1 周围的 () 将在子 shell 中运行这些命令。 return 只会让您退出子shell,而不是完全退出函数。您可以改用{} 来实现没有子shell 的命令分组。还要确保return 后跟;,然后再关闭}

 6          test $1 || { echo "no value"; return 1; }

请参阅Bash manual command grouping section 了解更多信息。

【讨论】:

    【解决方案2】:

    在括号内,returnexit 导致括号创建的子shell 退出,而不是执行... || ... 列表的shell。你想改用{...}

    function firstfunc {
        test $1 || { echo "no value"; return 1; }
        echo it looks like \"$1\" is  the first value of \$foo
        return 0
    }
    

    请注意,大括号比括号更挑剔:最后的命令必须后跟一个分号,并且您必须确保大括号与周围的字符用空格分隔。

    【讨论】:

      【解决方案3】:

      正如其他人所提到的,parens 创建一个子shell,exit 或 return 命令指示 bash 从子shell 退出。你应该使用花括号。请注意,您可以使用 bash 参数替换以更简单的方式获得相同的效果。见下文。

      您的行 test $variable || (echo "Value of \$variable cannot be null."; exit 1) 即使在函数上下文的“外部”也不应该工作。例如:

      $ cat t.sh 
      #!/bin/bash
      
      a="hello"
      test $a || (echo "Value of \$variable cannot be null."; exit 1)
      echo First test passed
      
      a=
      test $a || (echo "Value of \$variable cannot be null."; exit 1)
      echo Second test passed
      

      给出:

      $ ./t.sh 
      First test passed
      Value of $variable cannot be null.
      Second test passed
      $ 
      

      我们看到第二个echo 运行,即使它不应该运行。使用花括号是要走的路。

      $ cat t.sh 
      #!/bin/bash
      
      a="hello"
      test $a || { echo "Value of \$variable cannot be null."; exit 1 ; }
      echo First test passed
      
      a=
      test $a || { echo "Value of \$variable cannot be null."; exit 1 ; }
      echo Second test passed
      $ ./t.sh 
      First test passed
      Value of $variable cannot be null.
      $
      

      请注意,您可以使用 bash ${parameter:?err_msg} 构造进行参数替换:

      $ cat t.sh 
      #!/bin/bash
      
      a="hello"
      : ${a:?'a is null or undefined! Exiting..'}
      echo First test passed
      
      a=
      : ${a:?'a is null or undefined! Exiting..'}
      echo Second test passed
      
      $ ./t.sh 
      First test passed
      ./t.sh: line 9: a: a is null or undefined! Exiting..
      $
      

      【讨论】:

      • 首先,感谢您重申正确答案,使用花括号。其次,我后来意识到我在主脚本中使用parens语法进行的测试是因为我用-e调用了我的原始脚本,所以任何错误都会导致整个脚本终止。第三,也是最后——感谢 ${param:?err} 构造,我以前从未见过,它看起来非常有用。
      猜你喜欢
      • 1970-01-01
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-14
      • 2010-09-08
      相关资源
      最近更新 更多