获取 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

答案1

app=(yahoo gmail)
# ...
declare ${app/%/_pid}=$!

上面的这个看起来很奇怪。虽然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_yahoost_yahoo

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

但实际上只是使用关联数组。

另请参见例如

答案2

从问题转移到答案

经过大量的搜索和示例才最终在这个上投入了资金,但最终对我有用的是:

app=(yahoo gmail)

$(which offlineimap) -c offlineimaprc -o -a ${app} & declare ${app/%/_pid}=$!

wait $(eval echo \$${app}_pid) <<== THIS IS THE MAGIC SYNTAX

$(eval echo \$${app}_st)=$?  && if [[ $(eval echo \$${app}_st) -ne 0 ]];then error_msg ${app}; fi

相关内容