Bash

獲取以bash中另一個變數為前綴的變數的值

  • May 26, 2022

我在一堆帳戶上執行 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}=$!

上面的這個看起來很奇怪。Whileapp是一個數組,只需引用$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_yahoost_yahoo

app=yahoo
declare -n pid="pid_$app"
declare -n st="st_$app"
something... & pid=$!
wait "$pid"
st=$?

但實際上只是使用關聯數組。

參見例如

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