Attribuez simplement toutes les variables et écrivez la sortie en même temps.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Maintenant, si vous le faites:
f ; echo "$a $b $c"
Votre sortie est:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Notez qu'il s'agit entièrement de code portable POSIX. J'ai initialement défini c=la ''chaîne nulle car l'expansion des paramètres limite l'affectation + l'évaluation simultanée des variables à des valeurs uniquement numériques (comme $((var=num))) ou à des valeurs nulles ou inexistantes - ou, en d'autres termes, vous ne pouvez pas définir et évaluer simultanément une variable en une chaîne arbitraire si cette variable est déjà affectée à une valeur. Je m'assure donc qu'il est vide avant d'essayer. Si je ne vidais pas cavant d'essayer de l'assigner, l'expansion ne retournerait que l'ancienne valeur.
Juste pour démontrer:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newvaln'est pas affecté à $cinline car oldvalest développé dans ${word}, tandis que l' affectation $((arithmétique inline se produit toujours. Mais si n'a pas et est vide ou non défini ...=))$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
... newvalest alors à la fois affecté et développé $c.
Toutes les autres façons de procéder impliquent une forme d'évaluation secondaire. Par exemple, supposons que je souhaite affecter la sortie de f()à une variable nommée nameà un moment et varà un autre. Tel qu'il est actuellement écrit, cela ne fonctionnera pas sans définir la var dans la portée de l'appelant. Une manière différente pourrait ressembler à ceci, cependant:
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"
J'ai fourni un meilleur exemple formaté ci-dessous, mais, appelé comme ci-dessus, la sortie est:
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 avec des $ENVarguments différents ou:
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
La chose la plus délicate à faire pour évaluer deux fois est probablement de s'assurer que les variables ne cassent pas les guillemets et exécutent du code aléatoire. Plus une variable est évaluée, plus elle devient difficile. L'extension des paramètres aide beaucoup ici, et l'utilisation exportpar opposition à evalest beaucoup plus sûre.
Dans l'exemple ci-dessus, f()attribue d'abord $foutla ''chaîne nulle, puis définit les paramètres de position pour tester les noms de variables valides. Si les deux tests ne réussissent pas, un message est émis stderret la valeur par défaut de foutest affectée à $fout_name. Indépendamment des tests, cependant, $fout_nameest toujours affecté à l'un foutou au nom que vous spécifiez $foutet, éventuellement, votre nom spécifié reçoit toujours la valeur de sortie de la fonction. Pour illustrer cela, j'ai écrit cette petite forboucle:
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
Il joue avec certains noms de variables et extensions de paramètres. Si vous avez une question, il suffit de la poser. Cela n'exécute que les mêmes lignes dans la fonction déjà représentée ici. Il convient de mentionner au moins que les variables $aet $bse comportent différemment selon qu'elles sont définies lors de l'invocation ou déjà définies. Pourtant, le forne fait presque rien d'autre que formater l'ensemble de données et fourni par f(). Regarde:
###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'
$aet$bsont des variables locales dans votreffonction. Vous pourriezexportles faire, mais cela semble sommaire.