Basta assegnare tutte le variabili e scrivere l'output contemporaneamente.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Ora se lo fai:
f ; echo "$a $b $c"
Il tuo output è:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Si noti che questo è un codice portatile completamente POSIX. Inizialmente ho impostato c=
la ''
stringa nulla perché l'espansione del parametro limita l'assegnazione variabile simultanea + valutazione a solo valori numerici (come $((var=num))
) o da valori null o inesistenti - o, in altre parole, non è possibile impostare e valutare contemporaneamente una variabile in una stringa arbitraria se a quella variabile è già stato assegnato un valore. Quindi mi assicuro che sia vuoto prima di provare. Se non avessi svuotato c
prima di provare ad assegnarlo, l'espansione restituirebbe solo il vecchio valore.
Giusto per dimostrare:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval
non è assegnato a $c
inline perché oldval
è espanso in ${word}
, mentre si verifica sempre l' assegnazione $((
aritmetica inline . Ma se ha no ed è vuoto o non impostato ...=
))
$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
... quindi newval
viene subito assegnato e ampliato in $c
.
Tutti gli altri modi per farlo comportano una qualche forma di valutazione secondaria. Ad esempio, supponiamo di voler assegnare l'output di f()
a una variabile denominata name
in un punto e var
in un altro. Come attualmente scritto, questo non funzionerà senza impostare il var nell'ambito del chiamante. Un modo diverso potrebbe apparire così:
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"
Ho fornito un esempio meglio formattato di seguito, ma, chiamato come sopra, l'output è:
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
O con differenti $ENV
o argomenti:
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
Probabilmente la cosa più difficile da ottenere quando si tratta di valutare due volte è assicurarsi che le variabili non rompano le virgolette ed eseguano codice casuale. Più volte viene valutata una variabile, più diventa difficile. L'espansione dei parametri aiuta molto qui, e l'utilizzo export
al contrario eval
è molto più sicuro.
Nell'esempio sopra f()
assegna prima $fout
la ''
stringa nulla e quindi imposta i parametri posizionali per verificare i nomi di variabili validi. Se entrambi i test non vengono superati, viene emesso un messaggio stderr
e fout
viene assegnato il valore predefinito di $fout_name
. Indipendentemente dai test, tuttavia, $fout_name
viene sempre assegnato a uno fout
o al nome specificato $fout
e, facoltativamente, al nome specificato viene sempre assegnato il valore di output della funzione. Per dimostrarlo ho scritto questo piccolo for
loop:
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
Gioca con alcuni con nomi di variabili ed espansioni di parametri. Se hai una domanda, basta chiedere. Che esegue solo le stesse poche righe nella funzione già rappresentata qui. Vale la pena ricordare almeno che le variabili $a
e si $b
comportano diversamente a seconda che siano definite al momento dell'invocazione o impostate già. Tuttavia, for
non fa quasi altro che formattare il set di dati e fornito da f()
. Dare un'occhiata:
###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
e$b
sono variabili locali nella tuaf
funzione. Potrestiexport
averli, ma questo sembra impreciso.