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 c
avant 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
newval
n'est pas affecté à $c
inline car oldval
est 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
... newval
est 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 $ENV
arguments 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 export
par opposition à eval
est beaucoup plus sûre.
Dans l'exemple ci-dessus, f()
attribue d'abord $fout
la ''
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 stderr
et la valeur par défaut de fout
est affectée à $fout_name
. Indépendamment des tests, cependant, $fout_name
est toujours affecté à l'un fout
ou au nom que vous spécifiez $fout
et, éventuellement, votre nom spécifié reçoit toujours la valeur de sortie de la fonction. Pour illustrer cela, j'ai écrit cette petite for
boucle:
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 $a
et $b
se comportent différemment selon qu'elles sont définies lors de l'invocation ou déjà définies. Pourtant, le for
ne 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'
$a
et$b
sont des variables locales dans votref
fonction. Vous pourriezexport
les faire, mais cela semble sommaire.