2013-10-31 142 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 
} 

注意,括號比括號多一點挑剔:最後的命令必須跟一個分號,你必須確保大括號是通過空間從周圍的字符分隔。