for k in {0..49}; do a=$(($((2*$k))+1)); echo $a; done
Hola, necesito una expresión simplificada para la tercera línea, tal vez una que sí no use la sustitución de comandos.
Comentarios
Respuesta
Usando expansión aritmética:
for (( k = 0; k < 50; ++k )); do a=$(( 2*k + 1 )) echo "$a" done
Usando la anticuada utilidad expr
:
for (( k = 0; k < 50; ++k )); do a=$( expr 2 "*" "$k" + 1 ) echo "$a" done
Usando bc -l
( -l
no es realmente necesario en este caso ya que no se usan funciones matemáticas):
for (( k = 0; k < 50; ++k )); do a=$( bc -l <<<"2*$k + 1" ) echo "$a" done
Usando bc -l
como coproceso (actúa como una especie de servicio de cálculo en segundo plano):
coproc bc -l for (( k = 0; k < 50; ++k )); do printf "2*%d + 1\n" "$k" >&${COPROC[1]} read -u "${COPROC[0]}" a echo "$a" done kill "$COPROC_PID"
Ese último se ve (posiblemente) más limpio en ksh93
:
bc -l |& bc_pid="$!" for (( k = 0; k < 50; ++k )); do print -p "2*$k + 1" read -p a print "$a" done kill "$bc_pid"
¹ Esto me resolvió un problema una vez en el que necesitaba procesar una gran cantidad de entrada en un bucle. El procesamiento requirió algunos cálculos de punto flotante, pero generar bc
varias veces en el ciclo resultó ser extremadamente lento. Sí, podría haberlo resuelto de muchas otras formas, pero estaba aburrido …
Respuesta
Puedes simplificar:
a=$(($((2*$k))+1));
para:
a=$((2*k+1))
Responder
Puede usar el comando let
para forzar un cálculo.
let a="2*k+1"
Tenga en cuenta que no necesitamos $k
en esta estructura; un k
simple hará el trabajo.
Comentarios
- Eso falla si hay ' un archivo llamado
a=2whateverk+1
en el directorio. Peor aún, si hay ' un archivo llamadoa=2+b[$(reboot)]k+1
, que llama al comandoreboot
. Lo mejor es usar((...))
aquí (((a = 2 * k + 1))
), o la sintaxis POSIX:a=$((2 * k + 1))
- Podemos citarlo;
let a="2*k+1"
para resolver eso.
Respuesta
La expansión aritmética que probablemente necesite es la siguiente:
a=$(( 1+2*k ))
De hecho, no necesita usar una variable:
for k in {0..49}; do echo "$(( 1 + 2*k ))" done
O la variable de conteo podría moverse a un for ((…))
loop:
for (( k=0;k<50;k++ )); do a=$(( 1+2*k )) printf "%s\n" "$a" done
for ((…)) loop
Y, en ese caso, la expansión aritmética también podría ser movido al interior del bucle for:
for (( k=0 ; a=1+2*k , k<50 ; k++)); do printf "%s\n" "$a" done
O, para obtener todos los valores en una matriz:
for (( k=0 ; a[k]=1+2*k , k<49 ; k++ )); do :; done printf "%s\n" "${a[@]}"
Sin fórmula
Pero probablemente la forma más corta de evitar cualquier expansión aritmética es incrementar una variable dos veces:
for (( k=0,a=1 ; k<50 ; k++,a++,a++ )); do printf "%s\n" "$a" done
O, incluso más simple, simplemente use seq:
seq 1 2 100
bash
y noC
, así que elimine todas las;
: a menos que lo escriba en una línea singular.declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
$(( ... ))
es expansión aritmética, no sustitución de comandos.