2012-10-11 72 views
7

我發現了我的奇怪行爲,我無法解釋。 下面的代碼是工作確定:從subshel​​l返回值和輸出到局部變量

function prepare-archive { 
blah-blah-blah... 
_SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/") 
exit $? 
blah-blah-blah... 
} 

意味着我得到我期待值:

bash -x ./this-script.sh: 
++ exit 1 
+ _SPEC_FILE='/home/likern/Print/Oleg/print-service/packaging/print-service.spec 
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec' 
+ exit 1 

只要我添加local定義變量:

local _SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/") 

我獲得以下:

bash -x ./this-script.sh: 
++ exit 1 
+ local '_SPEC_FILE=/home/likern/Print/Oleg/print-service/packaging/print-service.spec 
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec' 
+ exit 0 
$:~/MyScripts$ echo $? 
0 

問題:爲什麼?發生了什麼?我能否將subshel​​l的輸出捕獲到local變量並可靠地檢查子殼的返回值?

P.S.在主shell腳本中調用prepare-archive。第一個exitexitcheck-spec-file函數,第二個從prepare-archive函數 - 這個函數本身是從主shell腳本執行的。我將check-spec-file的值返回exit 1,然後將此值傳遞給exit $?。因此我希望他們應該是一樣的。

+0

在什麼情況下調用'prepare-archive'? '++ exit 1'不適合你顯示的任何代碼。 – chepner

回答

4

從bash的手冊,Shell Builtin Commands部分:

local: 
    [...]The return status is zero unless local is used outside a function, an invalid name is supplied, or name is a readonly variable. 

希望這有助於=)

+0

這是否意味着變量定義在沒有'local'的情況下使用時沒有返回狀態?爲什麼?你知道一些解決方法 - 因爲我不想產生多餘的全局變量。 –

+0

我不知道任何解決方法,不涉及創建一個全局變量或文件的使用,sorry =(。我會做本地TMPFILE = $(mktemp);檢查spec文件> $ TMPFILE ;本地錯誤= $ ?;本地_SPEC_FILE = $(cat $ TMPFILE); rm $ TMPFILE' –

+1

@Mephi_stofel - 爲了解決它,你可以拆分聲明和初始化,例如第一個:local my_var',而不是: 'my_var = $(my_function)'。初始化將安全地引用局部變量,而不會污染全局範圍。 –

12

要捕獲子shell的退出狀態,分配前變量聲明爲局部的,例如,下面的腳本

#!/bin/sh 

local_test() 
{ 
    local local_var 
    local_var=$(echo "hello from subshell"; exit 1) 
    echo "subshell exited with $?" 
    echo "local_var=$local_var" 
} 

echo "before invocation local_var=$local_var in global scope" 
local_test 
echo "after invocation local_var=$local_var in global scope" 

產生以下輸出

before invocation local_var= in global scope 
subshell exited with 1 
local_var=hello from subshell 
after invocation local_var= in global scope 
+0

在這裏解釋發生了什麼?你的回答解決了我的問題,但我仍然不明白它是如何以及爲什麼這樣做的。 –

+1

@IhorKaharlichenko如果一個變量在'local'的聲明上被賦值,子shell退出狀態爲「masked」 /由出口s覆蓋「本地」內置命令的特徵。在賦值之前聲明局部變量也更加便攜(某些shell不支持用'local'初始化)。 – vilpan