He intentado incrementar una variable numérica usando ambos var=$var+1
y var=($var+1)
sin éxito. La variable es un número, aunque bash parece estar leyéndolo como una cadena.
Bash versión 4.2.45 (1) -release (x86_64-pc-linux-gnu) en Ubuntu 13.10.
He intentado incrementar una variable numérica usando ambos var=$var+1
y var=($var+1)
sin éxito. La variable es un número, aunque bash parece estar leyéndolo como una cadena.
Bash versión 4.2.45 (1) -release (x86_64-pc-linux-gnu) en Ubuntu 13.10.
Respuestas:
Hay más de una forma de incrementar una variable en bash, pero lo que intentó no es correcto.
Puede usar, por ejemplo, la expansión aritmética :
var=$((var+1))
((var=var+1))
((var+=1))
((var++))
O puedes usar let
:
let "var=var+1"
let "var+=1"
let "var++"
Ver también: http://tldp.org/LDP/abs/html/dblparens.html .
var=0; ((var++))
devuelve un código de error mientras var=0; ((var++)); ((var++))
que no. ¿Alguna idea de por qué?
help '(('
. La última línea dice:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
1
es la razón por la cual la sugerencia de @ gniourf_gniourf incluye ((++var))
pero no ((var++))
.
let var++
, sin las comillas?
var=$((var + 1))
La aritmética en bash usa la $((...))
sintaxis.
((...))
es la clave para usar la aritmética en fiesta No me di cuenta de que solo mirando la respuesta aceptada, pensé que había un conjunto extraño de reglas sobre el orden de las operaciones o algo que condujera a todos los paréntesis en la respuesta aceptada.
Gracias a la respuesta de Radu Rădeanu que proporciona las siguientes formas de incrementar una variable en bash:
var=$((var+1))
((var=var+1))
((var+=1))
((var++))
let "var=var+1"
let "var+=1"
let "var++"
También hay otras formas. Por ejemplo, mira las otras respuestas sobre esta pregunta.
let var++
var=$((var++))
((++var))
{
declare -i var
var=var+1
var+=1
}
{
i=0
i=$(expr $i + 1)
}
Tener tantas opciones lleva a estas dos preguntas:
#!/bin/bash
# To focus exclusively on the performance of each type of increment
# statement, we should exclude bash performing while loops from the
# performance measure. So, let's time individual scripts that
# increment $i in their own unique way.
# Declare i as an integer for tests 12 and 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Set i for test 14.
echo > t14 'i=0; i=$(expr $i + 1)'
x=100000
while ((x--)); do
echo >> t0 'i=$((i+1))'
echo >> t1 'i=$((i++))'
echo >> t2 '((i=i+1))'
echo >> t3 '((i+=1))'
echo >> t4 '((i++))'
echo >> t5 '((++i))'
echo >> t6 'let "i=i+1"'
echo >> t7 'let "i+=1"'
echo >> t8 'let "i++"'
echo >> t9 'let i=i+1'
echo >> t10 'let i+=1'
echo >> t11 'let i++'
echo >> t12 'i=i+1'
echo >> t13 'i+=1'
echo >> t14 'i=$(expr $i + 1)'
done
for script in t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; do
line1="$(head -1 "$script")"
printf "%-24s" "$line1"
{ time bash "$script"; } |& grep user
# Since stderr is being piped to grep above, this will confirm
# there are no errors from running the command:
eval "$line1"
rm "$script"
done
i=$((i+1)) user 0m0.992s
i=$((i++)) user 0m0.964s
((i=i+1)) user 0m0.760s
((i+=1)) user 0m0.700s
((i++)) user 0m0.644s
((++i)) user 0m0.556s
let "i=i+1" user 0m1.116s
let "i+=1" user 0m1.100s
let "i++" user 0m1.008s
let i=i+1 user 0m0.952s
let i+=1 user 0m1.040s
let i++ user 0m0.820s
declare -i i; i=i+1 user 0m0.528s
declare -i i; i+=1 user 0m0.492s
i=0; i=$(expr $i + 1) user 0m5.464s
Parece que bash es más rápido i+=1
cuando $i
se declara como un entero. let
Las declaraciones parecen particularmente lentas, y expr
es, con mucho, la más lenta porque no está integrada.
También hay esto:
var=`expr $var + 1`
Tome nota de los espacios y también ' no es '
Si bien las respuestas de Radu y los comentarios son exhaustivos y muy útiles, son específicos de bash. Sé que preguntaste específicamente sobre bash, pero pensé en hablar desde que encontré esta pregunta cuando estaba buscando hacer lo mismo usando sh en busybox en uCLinux. Este portátil más allá de bash.
i=$((i+1))
$(...)
está disponible en este shell, recomendaría usarlo en su lugar.
Si declaras $var
como un entero, lo que intentaste la primera vez realmente funcionará:
$ declare -i var=5
$ echo $var
5
$ var=$var+1
$ echo $var
6
Referencia: Tipos de variables, Guía Bash para principiantes
Falta un método en todas las respuestas: bc
$ VAR=7
$ bc <<< "$VAR+2"
9
$ echo $VAR
7
$ VAR=$( bc <<< "$VAR+1" )
$ echo $VAR
8
bc
está especificado por el estándar POSIX , por lo que debe estar presente en todas las versiones de Ubuntu y sistemas compatibles con POSIX. La <<<
redirección podría modificarse echo "$VAR" | bc
para la portabilidad, pero dado que la pregunta se refiere a bash
: está bien usarla <<<
.
El código de retorno 1
tema está presente para todas las variantes (por defecto let
, (())
, etc.). Esto a menudo causa problemas, por ejemplo, en los scripts que usan set -o errexit
. Esto es lo que estoy usando para evitar que el código de error 1
de las expresiones matemáticas evalúen 0
;
math() { (( "$@" )) || true; }
math a = 10, b = 10
math a++, b+=2
math c = a + b
math mod = c % 20
echo $a $b $c $mod
#11 12 23 3
Esta tiene que ser la peor manera de lograr una tarea tan simple, pero supongo que solo quería documentarlo por diversión (completamente opuesto al código golf).
$ var=0
$ echo $var
0
$ var="$(python -c 'print('$var'+1)')"
$ echo $var
1
o
$ var="$(printf '%s\n' $var'+1' | bc)"
$ echo $var
1
En serio, use una de las otras opciones mucho mejores aquí.
((++var))
o((var=var+1))
o((var+=1))
.