Bash

如何使子shell中的變數在父shell中可用

  • July 18, 2018

我已經編寫了一個快速而骯髒的腳本來為來自 Web 服務的一些報告計時:

BASE_URL='http://example.com/json/webservice/'
FIRST=1
FINAL=10000

for report_code in $(seq 1 $FINAL); do
 (time -p response=$(curl --write-out %{http_code} --silent -O ${BASE_URL}/${report_code}) ) 2> ${report_code}.time

 echo $response  # <------- this is out of scope!  How do I fix that?
 if [[ $response = '404' ]]; then
   echo "Deleting report # ${report_code}!"
   rm ${report_code}
 else
   echo "${report_code} seems to be good!"
 fi
done

我需要將time命令包裝在一個子 shell 中,以便我可以重定向它的輸出,但這使得$response父 shell 的值不可用。我該如何解決這個問題?

您不能將變數的值從子外殼帶到其父外殼,除非進行一些容易出錯的編組和繁瑣的通信。

幸運的是,這裡不需要子shell。重定向只需要命令分組{ … }而不是子shell。

{ time -p response=$(curl --write-out '%{http_code}' --silent -O "${BASE_URL}/${report_code}"); } 2> "${report_code}.time"

(不要忘記變數替換的雙引號。)

U&L 使用者:在否決我使用 C 風格與main()函式的答案之前,請訪問此連結:https ://unix.stackexchange.com/a/313561/85039在腳本中使用主要函式是一種常見做法,許多專業人士都在使用在該領域。


正如 Gilles 所指出的,子 shell 不能使變數在其環境之外可用。但是讓我們從另一個角度來解決這個問題——如果你在函式中編寫腳本,就可以將變數聲明為local並且可以編輯。

來自 bash 4.3 的手冊,local描述:

…當在函式中使用 local 時,它會導致變數名具有僅限於該函式及其子級的可見範圍…

例子:

#!/bin/bash

outter()
{
   for i in $(seq 1 3)
   do
       var=$i
   done
}

main()
{
   local var=0
   outter
   echo $var
}
main "$@"
$ ./testscript.sh                                                                                                        
3

正如您在循環函式的 3 次迭代後看到的那樣,變數已被修改。

引用自:https://unix.stackexchange.com/questions/140043