lunes, 17 de julio de 2017

Lógica

Como descubrimos en el Capítulo 27, el comando compuesto (( )) soporta una variedad de operadores de comparación. Hay unos pocos más que pueden usarse para evaluar la lógica. Aquí tenemos la lista completa:

Tabla 34-6: Operadores de comparación
Operador Descripción
<= Menor o igual que
>= Mayor o igual que
< Menor que
> Mayor que
== Igual a
!= No igual a
&& AND lógico
|| OR lógico
expr1?expr2:expr3 Operador de comparación (ternario). Si expr1 se evalúa como distinta de cero (aritmética verdadera) entonces expr2, si no expr3.

Cuando se usan para operaciones lógicas, las expresiones siguen las reglas de la lógica aritmética; es decir, las expresiones que se evalúan como cero se consideran falsas, mientras que las expresiones distintas de cero se consideran verdaderas. El comando compuesto (( )) mapea los resultados dentro de los códigos de salida normales de shell:

[me@linuxbox ~]$ if ((1)); then echo "true"; else echo "false"; fi
true
[me@linuxbox ~]$ if ((0)); then echo "true"; else echo "false"; fi
false

El operador lógico más extraño es el operador ternario. Este operador (que se modeló después del que hay en el lenguaje de programación C) realiza un test lógico autónomo. Puede usarse como un tipo de sentencia if/then/else. Actúa en tres expresiones aritméticas (las cadenas no funcionarán), y si la primera expresión es verdadera (o distinta de cero) se ejecuta la segunda expresión. Si no, se ejecuta la tercera expresión. Podemos probarlo en la línea de comandos:

[me@linuxbox ~]$ a=0
[me@linuxbox ~]$ ((a<1?++a:--a))
[me@linuxbox ~]$ echo $a
1
[me@linuxbox ~]$ ((a<1?++a:--a))
[me@linuxbox ~]$ echo $a
0

Aquí vemos al operador ternario en acción. Este ejemplo implementa un interruptor. Cada vez que el operador se ejecuta, el valor de la variable a cambia de cero a uno o viceversa.

Por favor, fíjate que realizar asignación dentro de expresiones no es sencillo.

Cuando lo intentamos, bash devuelve un error:

[me@linuxbox ~]$ a=0
[me@linuxbox ~]$ ((a<1?a+=1:a-=1))
bash: ((: a<1?a+=1:a-=1: attempted assignment to non-variable (error token is "-=1")

Este problema puede evitarse incluyendo la expresión de asignación entre paréntesis:

[me@linuxbox ~]$ ((a<1?(a+=1):(a-=1)))

A continuación, vemos un ejemplo más completo del uso de operadores aritméticos en un script que produce una tabla simple de números:

#!/bin/bash

# arith-loop: script to demonstrate arithmetic operators

finished=0
a=0
printf "a\ta**2\ta**3\n"
printf "=\t====\t====\n"

until ((finished)); do
    b=$((a**2))
    c=$((a**3))
    printf "%d\t%d\t%d\n" $a $b $c
    ((a<10?++a:(finished=1)))
done

En este script, implementamos un bucle until basado en el valor de la variable finished. Inicialmente, la variable está establecida en cero (aritmética falsa) y continuamos el bucle hasta que se convierta en distinta de cero. Dentro del bucle, calculamos el cuadrado y el cubo de la variable contador a. Al final del bucle, el valor de la variable contador se evalúa. Si es menor de 10 (el número máximo de iteraciones), se incrementa en uno, si no, se le da a la variable finished el valor de uno, haciendo a finished aritméticamente verdadera, y terminando de esta forma el bucle. Ejecutar el script da este resultado:

[me@linuxbox ~]$ arith-loop
a   a**2   a**3
=   ====   ====
0   0      0
1   1      1
2   4      8
3   9      27
4   16     64
5   25     125
6   36     216
7   49     343
8   64     512
9   81     729
10  100    1000

No hay comentarios:

Publicar un comentario