Mar 262008
 

La ganadería fue una práctica del hombre en la prehistoria, y con la necesidad de contar el ganado surgió el cálculo. La palabra cálculo en si proviene del latín ‘calculus’, piedra pequeña. Se dice que para contar el ganado se usaban inicialmente piedrecitas, por cada cabeza de ganado que salía a pastar se guardaba una piedra, y cuando la res volvía al redil se tiraba una de las piedras guardadas. Cuando ya no quedaban más piedras todos los animales estaban a buen recaudo.


Las cosas han cambiado mucho pero nuestra necesidad de ‘contar’ sigue ahí, solo que ahora los métodos son algo más sofisticados. Bash puede manejar números enteros y realizar con ellos operaciones aritméticas simples (o no tanto). Bash no maneja números reales, sólo enteros

let

El comando (interno) let se utiliza básicamente para realizar operaciones aritméticas simples y generalmente asignar el resultado a una variable, de esta forma:

$ let a=3+2
$ echo $a
5
$ let b=a+1 c=b+2
$ echo $a $b $c
5 6 8

En cada comando let se pueden evaluar varias expresiones. Cada expresión tiene que ser una sola palabra, si se dejan espacios hay que entrecomillarlos.

$ let "a = 3 + 2" "b = a + 1"
$ echo $a $b
5 6

Fíjate que en las expresiones puede haber nombres de variables, que siempre se evaluarán como el valor de esta variable. No es necesario que se utilice la expansión de parámetros del bash ($variable o ${variable}) para que la variable se sustituya por su valor, pero en caso de usarla hay que tener en cuenta que la expansión se hace de forma previa a la evaluación.

$ a=5
$ let a=a+1 b=a*2
$ echo $a $b
6 12

Cuando se evalúa la segunda expresión la variable a contiene el valor modificado por la primera expresión, en cambio si usamos la expansión de parámetros de bash, primero se expanden todas las $a por su valor que es 5 y luego se evalúan las expresiones:

$ a=5
$ let a=$a+1 b=$a*2
$ echo $a $b
6 10

Asignación de valores

La asignación de valores en let se hace de forma similar a la asignación de variables normales, indicando un nombre de variable seguida de un signo igual y de una exporesión, se asigna el valor de esa expresión a la variable. Con valores simples no es necesario el let:

$ a=5
$ echo $a
5
$ let a=5
$ echo $a
5

Pero si queremos que se evalúen las expresiones es necesario poner el let:

$ a=8**2
echo $a
8**2
$ let a=8**2
echo $a
64

Operaciones aritméticas

Let puede realizar las siguientes operaciones aritméticas:

  • + Suma
  • Resta
  • * Producto
  • / División entera
  • % Resto de la división entera
  • ** Potencia

Ejemplo:

$ let X=3+2 Y=4*7 RESTO=7%2 DIV=345/6 CUADRADO=5**2
$ echo $X $Y $RESTO $DIV $CUADRADO
5 28 1 57 25

Modificación del valor de una variable in situ (Asignación compuesta)

Cuando necesitamos modificar el valor de una variable realizando cierta operación con él, en la mayoría de los lenguajes debemos recurrir a asignar a dicha variable el resultado de una expresión en la que interviene la propia variable. Por ejemplo si queremos sumar 4 al valor que tenía X debemos poner ‘let X=X+4′, esa expresión es matemáticamente un absurdo, pero en lenguaje informático quiere decir, ‘asigna a X el valor resultante de sumar 4 a su antiguo valor’. En bash podemos hacerlo así, pero además existe una forma abreviada, que os sonará a aquellos que habéis programado en C, o en php: X+=4. El operador += es un operador de asignación igual que el = y por tanto tiene que ir a continuación de una variable, y se usa para sumar a dicha variable el operando que viene a continuación del operador, dejando el resultado en la misma variable, digamos que es como ‘sumar in situ’.

$ X=3
$ let X+=3
$ echo $X
6

Con el resto de operaciones aritméticas tenemos operadores de asignación compuesta similares:

  • Var+=Expr Sumar in situ
  • Var-=Expr Restar in situ
  • Var*=Expr Multiplicar in situ
  • Var/=Expr Dividir in situ
  • Var%=Expr Resto de división in situ

Preincremento, predecremento, postincremento y postdecremento

Para sumar una unidad a una variable (X=X+1) podemos usar el operador ++. Poner X++ o ++X es aproximadamente lo mismo que poner X+=1 y es más corto. La diferencia es que X++ ó ++X puede funcionar además como operando. X++ devuelve el valor de X antes de ser incrementada y ++X devuelve el valor después de ser incrementado. Veamos ejemplos:

$ let A=5 A++
$ echo $A
6
$ let X=A++
$ echo $X $A
6 7
$ let X=++A
$ echo $X $A
8 8

A estos operadores se les suele llamar postincremento (Var++) y preincremento (++Var), y para no ser menos también existen el postdecremento (Var–) y el predecremento (–Var) que son lo mismito pero restan 1 en vez de sumarlo, simple ¿no?.

Comparaciones

Aunque no suele usarse mucho let, además de para asignar valores a variables también se puede usar para hacer comparaciones, que devuelven cierto o falso. Tal que así:


$let "4>5" ; echo "Resultado=$? (0=Cierto, 1=Falso)"

Las operaciones de comparación admitidas son:

  • == Igual
  • != Distinto
  • > Mayor que
  • < Menor que
  • >= Mayor o igual que
  • <= Menor o igual que

Con ya esto podemos construir expresiones condicionales. Aunque más adelante veremos como evaluar expresiones condicionales de otra forma que se usa bastante más que let.


read -p "Cuantos años tienes:" edad; let "edad>=18" && echo "Que bien, ya puedes votar";\
let "edad<30" && echo "Eres un chaval"

Fijaros que siempre que haya un símbolo de > o < hay que escaparlo, o mejor todavía entrecomillar la expresión para que bash no interprete el símbolo como una redirección.

Varias comparaciones pueden asociarse mediante los operadores lógicos:

  • && And
  • || Or
  • ! Not
  • Lógica booleana y operaciones de bits

    Y además de las comparaciones y las operaciones aritméticas let permite hacer una serie de operaciones booleanas. Hay que tener en cuenta que al fin y al cabo todos los números para el ordenador son binarios, y estas operaciones funcionan a nivel de bits. No quiero profundizar en aritmética booleana, pero si quiero citar las operaciones posibles:

    • & And a nivel de bits (Producto booleano)
    • | Or a nivel de bits (Suma booleana)
    • ^ Or exclusivo a nivel de bits
    • ~ Negación a nivel de bits
    • >> Desplazamiento de bits a la izquierda
    • << Desplazamiento de bits a la derecha

    Otra forma de escribir let

    Encerrar una expresión entre doble paréntesis es exactamente lo mismo que usar el comando let con la ventaja de que el doble paréntesis ya actúa como delimitador de la expresión y no es necesario el escapado o entrecomillado que casi siempre necesitaremos con let. Veámos como sería con el ejemplo anterior:


    read -p "Cuantos años tienes:" edad; ((edad>=18)) && echo "Que bien, ya puedes votar";\
    ((edad<30)) && echo "Eres un chaval"

    Sustitución aritmética

    En una orden aparece una expresión aritmética encerrada en doble paréntesis la precedemos de un signo de $ se evaluará la expresión y se sustituirá toda ella por su resultado previamente a la ejecución de la orden, de manera similar a como se sustituyen las variables por su valor.

    $ echo $((3 + 2))
    5

    Variables enteras

    Básicamente bash permite almacenar números en variables, si una variable contiene un número puede tratarse como tal, y hacer operaciones con el. Si se intenta hacer una operación aritmética en la que intervenga como operador una variable que no contenga un número entero válido se considerará que contiene un cero. Se pueden declarar las variables como enteras pero no es obligatorio hacerlo. Al declarar una variable como entera solo podrá contener números, el intento de asignarle cualquier cosa que no sea un número entero asignará el valor cero, pero no dará error.
    $ VAR1=hola
    $ declare -i VAR2
    $ VAR2=hola
    $ echo $VAR1 $VAR2
    hola 0