2013-10-31 146 views
1

我习惯于测试一个变量具有非空值分组(或发出的信息和保释)使用这样一行:bash命令测试结果在功能

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 

在第一个功能时,没有价值我得到的第一个C “或”命令组的ommand和“无值”回声,但返回命令被传递并且函数的其余部分被执行,直到返回。

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

+1

的括号不是命令的分组,他们在子shell中运行所包含的命令。使用'{...}'进行命令分组而不创建子shell。 – Barmar

回答

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运行,即使它shoulnd't有。使用大括号是要走的路。

$ 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.. 
$ 
+0

首先,谢谢你重申正确的答案,使用大括号。其次,后来我意识到我在主脚本中使用parens语法的测试是因为我用-e调用了我的原始脚本,所以任何错误都会导致整个脚本终止。 第三,最后 - 感谢$ {param:?err}结构,之前我没有看到它,它看起来非常有用。 – jg3

1

()echo "no value"; return 1将在子shell中运行这些命令。 return只会将您退出子shell,而不是完全退出该功能。您可以使用{}来实现无子shell的命令分组。还要确保return后跟;收盘}前:

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

更多信息,请参见Bash manual command grouping section

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 
} 

注意,括号比括号多一点挑剔:最后的命令必须跟一个分号,你必须确保大括号是通过空间从周围的字符分隔。