bash命令分组功能中的测试结果

时间:2013-10-31 21:20:11

标签: bash function testing parentheses

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

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

在没有值的第一个函数中,我得到“或”命令组的第一个命令,并且“无值”回显,但返回命令被传递,其余的函数被执行,向下回归。

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

3 个答案:

答案 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..
$

答案 1 :(得分: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 :(得分:1)

在括号内,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
}

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