Apenas atribua todas as variáveis e escreva a saída ao mesmo tempo.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Agora, se você fizer:
f ; echo "$a $b $c"
Sua saída é:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Observe que este é um código portátil totalmente POSIX. Inicialmente, defino c=a ''cadeia nula porque a expansão do parâmetro limita a atribuição simultânea de variáveis + a avaliação a valores numéricos (como $((var=num))) ou nulos ou inexistentes - ou, em outras palavras, você não pode configurar e avaliar simultaneamente uma variável em uma cadeia arbitrária se essa variável já tiver um valor atribuído. Portanto, apenas garanto que ele esteja vazio antes de tentar. Se eu não esvaziasse cantes de tentar atribuí-lo, a expansão retornaria apenas o valor antigo.
Apenas para demonstrar:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newvalnão é atribuído ao $cinline porque oldvalé expandido para ${word}, enquanto a atribuição $((aritmética inline sempre ocorre. Mas se não tem e está vazio ou não está definido ...=))$c oldval
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
c= a=$((a+a))
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval 8
... então newvalé imediatamente atribuído e expandido para $c.
Todas as outras maneiras de fazer isso envolvem alguma forma de avaliação secundária. Por exemplo, digamos que eu desejasse atribuir a saída de f()a uma variável nomeada nameem um ponto e varem outro. Como está escrito atualmente, isso não funcionará sem definir o var no escopo do chamador. Uma maneira diferente poderia ser assim:
f(){ fout_name= fout= set -- "${1##[0-9]*}" "${1%%*[![:alnum:]]*}"
(: ${2:?invalid or unspecified param - name set to fout}) || set --
export "${fout_name:=${1:-fout}}=${fout:=$(date): $((a=${a:-50}+1)) $((b=${b:-100}-4))}"
printf %s\\n "$fout"
}
f &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$a" "$b"
Forneci um exemplo melhor formatado abaixo, mas chamado como acima, a saída é:
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
51
96
Ou com diferentes $ENVou argumentos:
b=9 f myvar &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$myvar" \
"$a" "$b"
###OUTPUT###
Tue Jul 1 19:56:42 PDT 2014: 52 5
myvar
Tue Jul 1 19:56:42 PDT 2014: 52 5
Tue Jul 1 19:56:42 PDT 2014: 52 5
52
5
Provavelmente, a coisa mais difícil de acertar quando se trata de avaliar duas vezes é garantir que as variáveis não quebrem aspas e executem códigos aleatórios. Quanto mais vezes uma variável é avaliada, mais difícil fica. A expansão de parâmetros ajuda bastante aqui, e usar exportao contrário evalé muito mais seguro.
No exemplo acima, f()primeiro atribui $fouta ''cadeia nula e, em seguida, define parâmetros posicionais para testar nomes de variáveis válidos. Se ambos os testes não passarem, uma mensagem será emitida stderre o valor padrão de foutserá atribuído $fout_name. Independentemente dos testes, no entanto, $fout_namesempre é atribuído a um foutou ao nome que você especificar $foute, opcionalmente, seu nome especificado sempre recebe o valor de saída da função. Para demonstrar isso, escrevi este pequeno forloop:
for v in var '' "wr;\' ong"
do sleep 10 &&
a=${a:+$((a*2))} f "$v" || break
echo "${v:-'' #null}"
printf '#\t"$%s" = '"'%s'\n" \
a "$a" b "$b" \
fout_name "$fout_name" \
fout "$fout" \
'(eval '\''echo "$'\''"$fout_name"\")' \
"$(eval 'echo "$'"$fout_name"\")"
done
Ele brinca com alguns com nomes de variáveis e expansões de parâmetros. Se tiver alguma questão, basta perguntar. Isso executa apenas as mesmas poucas linhas na função já representada aqui. Vale ressaltar, pelo menos, que as variáveis $ae $bse comportam de maneira diferente, dependendo se elas estão definidas na chamada ou já estão definidas. Ainda assim, forele quase não formata o conjunto de dados e é fornecido por f(). Dar uma olhada:
###OUTPUT###
Wed Jul 2 02:50:17 PDT 2014: 51 96
var
# "$a" = '51'
# "$b" = '96'
# "$fout_name" = 'var'
# "$fout" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:27 PDT 2014: 103 92
'' #null
# "$a" = '103'
# "$b" = '92'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:37 PDT 2014: 207 88
wr;\' ong
# "$a" = '207'
# "$b" = '88'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
$ae$bsão variáveis locais em suaffunção. Você poderiaexport, mas isso parece incompleto.