Bash
獲取以bash中另一個變數為前綴的變數的值
我在一堆帳戶上執行 offlineimap,並希望檢查每次執行的退出程式碼並相應地執行一些操作。
我有 6 個獨立的電子郵件帳戶,我使用大量重複程式碼執行這些帳戶。原來的命令結構是:
$ $(which offlineimap) -c offlineimaprc -o -a yahoo & declare yahoo_pid=$! wait $yahoo_pid yahoo_st=$? if [[ $yahoo_st -ne 0 ]];then <do some stuff> $ $(which offlineimap) -c offlineimaprc -o -a gmail & declare gmail_pid=$! wait $gmail_pid gmail_st=$? if [[ $gmail_st -ne 0 ]];then <do some stuff>
現在我想刪除重複項並從
for in
循環和wait
命令中執行它。${account-name}_pid(例如 yahoo_pid)替換工作正常,但我被命令卡住了wait
。$ for app in yahoo gmail do $(which offlineimap) -c offlineimaprc -o -a ${app} & declare ${app/%/_pid}=$! wait ${app}_pid done [1] 73443 -bash: wait: `$yahoo_pid': not a pid or valid job spec [2] 73444 -bash: wait: `$gmail_pid': not a pid or valid job spec
app=(yahoo gmail) # ... declare ${app/%/_pid}=$!
上面的這個看起來很奇怪。While
app
是一個數組,只需引用$app
就會從數組中獲取第一個元素,與${arr[0]}
. 所以那總是分配給yahoo_pid
.$(eval echo \$${app}_st)=$?
這根本行不通。在等號左側有一個擴展使其成為無效分配,shell 會將其作為命令處理。如果
$yahoo_st
未設置,並且$?
例如是0
,它將嘗試執行一個名為=0
.無論如何,就你的情況而言。
Bash 有關聯數組,即由字元串索引的數組,它們幾乎就是您在這裡所需要的。它們需要用 聲明
declare -A
,可以像上面那樣分配正常數組。imap=$(which offlineimap) apps=(yahoo gmail) declare -A pids=() declare -A st=() for app in "${apps[@]}"; do "$imap" -c offlineimaprc -o -a "$app" & pids[$app]=$! wait "${pids[$app]}" st[$app]=$? done # and to check on them later: for app in "${apps[@]}"; do printf "app '%s' ran pid %s returning status %s\n" "$app" "${pids[$app]}" "${st[$app]}" done
或者可能:
for app in "${apps[@]}"; do "$imap" -c offlineimaprc -o -a "$app" & pids[$app]=$! done for app in "${apps[@]}"; do wait "${pids[$app]}" st[$app]=$? done # ...
或者,您可以使用 namerefs 來引用在另一個中命名的變數。這將設置
pid_yahoo
和st_yahoo
:app=yahoo declare -n pid="pid_$app" declare -n st="st_$app" something... & pid=$! wait "$pid" st=$?
但實際上只是使用關聯數組。
參見例如