Simplemente asigne todas las variables y escriba la salida al mismo tiempo.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Ahora si lo haces:
f ; echo "$a $b $c"
Su salida es:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Tenga en cuenta que este es un código portátil POSIX completo. Inicialmente configuré c=
la ''
cadena nula porque la expansión de parámetros limita la asignación de variables concurrentes + evaluación a valores numéricos (similares $((var=num))
) o nulos o inexistentes, o, en otras palabras, no puede establecer y evaluar una variable a una cadena arbitraria al mismo tiempo si esa variable ya tiene asignado un valor. Así que solo me aseguro de que esté vacío antes de intentarlo. Si no vacíe c
antes de intentar asignarlo, la expansión solo devolverá el valor anterior.
Solo para demostrar:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval
no está asignado a en $c
línea porque oldval
se expande en ${word}
, mientras que la asignación $((
aritmética en línea siempre ocurre. Pero si no tiene y está vacío o desarmado ...=
))
$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
... luego newval
se asigna y se expande a la vez $c
.
Todas las demás formas de hacerlo implican alguna forma de evaluación secundaria. Por ejemplo, supongamos que deseo asignar la salida de f()
una variable nombrada name
en un punto y var
en otro. Como está escrito actualmente, esto no funcionará sin establecer la var en el alcance de la persona que llama. Sin embargo, una forma diferente podría verse así:
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"
He proporcionado un ejemplo mejor formateado a continuación, pero, llamado como arriba, el resultado es:
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 diferentes $ENV
o 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
Probablemente, lo más difícil de hacer bien cuando se trata de evaluar dos veces es asegurarse de que las variables no rompan las comillas y ejecuten código aleatorio. Cuantas más veces se evalúa una variable, más difícil se vuelve. La expansión de parámetros ayuda mucho aquí, y el uso export
en lugar de eval
es mucho más seguro.
En el ejemplo anterior, f()
primero asigna $fout
la ''
cadena nula y luego establece los parámetros posicionales para probar nombres de variables válidos. Si ambas pruebas no pasan, se emite un mensaje stderr
y fout
se le asigna el valor predeterminado de $fout_name
. Sin embargo, independientemente de las pruebas, $fout_name
siempre se asigna a uno fout
o al nombre que especifique $fout
y, opcionalmente, a su nombre especificado siempre se le asigna el valor de salida de la función. Para demostrar esto escribí este pequeño for
bucle:
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
Juega alrededor de algunos con nombres de variables y expansiones de parámetros. Si tiene alguna pregunta, solo pregunte. Eso solo ejecuta las mismas pocas líneas en la función ya representada aquí. Vale la pena mencionar al menos que las variables $a
y se $b
comportan de manera diferente dependiendo de si están definidas en la invocación o si ya están configuradas. Aún así, el for
hace casi nada más que formatear el conjunto de datos y proporcionado por f()
. Echar un vistazo:
###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
y$b
son variables locales en suf
función. Podríasexport
, pero eso parece incompleto.