2016-02-03 18 views
2

在bash編程中,我目前面臨的一個問題是,我不僅想要在bash函數中修改全局變量,還要通過return$?返回適當的返回代碼,並且能夠分配所有在出現期間出現的stdout輸出函數調用函數外的變量。如何在捕獲標準輸出的同時修改bash函數中的全局變量並返回有效的返回碼?

雖然這些單獨的任務(修改全局var,返回狀態碼,將stdout分配給變量)似乎完全可能在bash中(甚至是這些願望中的兩個的組合),所有這三個需求的組合幾乎不可能(即只是不方便)。

下面是一個例子腳本我已經準備演示此問題:

#!/bin/bash 
# 
# This is the required output: 
# 
# -- cut here -- 
# RETURN: '2' 
# OUTPUT: 'Hello World!' 
# GLOBAL_VAR: '3' 
# -- cut here -- 
# 

GLOBAL_VAR=0 

hello() { 
    echo "Hello World!" 
    GLOBAL_VAR=3 
    return 2 
} 

# (1) normal bash command substition (subshell) 
#  PROBLEM: GLOBAL_VAR is 0 but should be 3 
#    (hello is executed in subshell) 
# 
output=$(hello) ; result=$? 

# (2) use 'read' and a reverse pipe 
#  PROBLEM: RETURN and GLOBAL_VAR is 0 
#    (hello in subshell and read return 
#    code returned) 
# 
#read output < <(hello) ; result=$? 

# (3) normal function execution 
#  PROBLEM: no catched output! 
# 
#hello ; result=$? 

# (4) using lastpipe + read 
#  PROBLEM: GLOBAL_VAR is 0 but should be 3 
#    (a pipe generateѕ a subshell?!?!) 
# 
#shopt -s lastpipe 
#hello | read output ; result=${PIPESTATUS[0]} 

# (5) ksh-like command substiution 
#  PROBLEM: Works, but ksh-syntax 
#    -> doesn't work in bash! 
# 
#output=${ hello; } ; result=$? 

# (6) using a temp file to catch output of hello() 
#  WORKS, but ugly due to tmpfile and 2xsubshell use! 
# 
#tmp=$(mktemp) 
#hello >${tmp} ; result=$? 
#output=$(cat ${tmp}) 
#rm -f ${tmp} 

################################### 
# OUTPUT stuff 

# this should output "2" 
echo "RESULT: '${result}'" 

# this should output "Hello World!" 
echo "OUTPUT: '$output'" 

# this should output "3" 
echo "GLOBAL_VAR: '$GLOBAL_VAR'" 

在這個腳本中我添加了一個函數hello()它應該返回2的狀態代碼,設置全局變量GLOBAL_VAR至3和輸出「Hello World!」到stdout。 除了這個功能外,我還增加了6個潛在的解決方案來調用這個hello()函數來實現我需要的輸出(它顯示在bash腳本代碼的頂部)。

通過在這6種不同的調用函數的方式中進行註釋,您將看到只有解決方案(6)才能滿足調用該函數的所有要求。

特別有趣的是,解決方案編號(5)顯示了ksh-syntax,它的工作原理與我需要此功能的工作方式完全相同。因此,使用ksh調用此腳本將輸出具有所需值的所有變量。當然,這個解決方案(使用${ cmd; }的命令替換)在bash中不受支持。然而,我肯定需要一個bash解決方案作爲主要腳本,我需要我的解決方案是一個僅限bash的腳本,我無法移植到ksh。

當然,解決方案(6)也符合我的要求,它需要將hello()的輸出放在一個臨時文件中,然後再讀取它。在性能方面(需要幾個子shell,臨時文件管理),這對我來說不是真正的解決方案。

所以現在問題出現了,如果在bash中有其他任何潛在的解決方案滿足我的要求,以便上面的腳本完全符合我的要求,因此結合了我所有的三個要求?!?

+1

我會使用解決方案#6 –

+0

如果#6中的性能問題是一個實際問題,'bash'可能不是該程序的正確語言。 – chepner

+3

我認爲你應該重新設計解決方案,而不需要將該函數設置爲全局變量。 – hek2mgl

回答

0

從問題中不清楚爲什麼您不能簡單地重寫函數以表現不同。如果你真的不能改變功能,你可以改變bash:

#!/bin/bash 

GLOBAL_VAR=0 

hello() { 
    echo "Hello World!" 
    GLOBAL_VAR=3 
    return 2 
} 

echo() { output=$*; } 
hello 
result=$? 
unset -f echo 

# this should output "2" 
echo "RESULT: '$result'" 

# this should output "Hello World!" 
echo "OUTPUT: '$output'" 

# this should output "3" 
echo "GLOBAL_VAR: '$GLOBAL_VAR'" 

輸出符合預期。

相關問題