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)=$?

이것은 단순히 작동하지 않습니다. 등호 왼쪽의 확장은 이를 잘못된 할당으로 만들고 쉘은 이를 명령으로 처리합니다. $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=$?

그러나 실제로는 연관 배열을 사용하십시오.

예를 들어 참조하십시오.

答え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

関連情報