Subsections

Scripts, loops y condicionales

Introducción a Scripts en bash

Un script es muy similar a un programa, aunque se puede correr solamente dentro de un contexto específico. Los shell scripts son un tipo de script desarollado para correr dentro de un terminal, como el de bash.
Todos los shell scripts que encontraremos en este curso (incluyendo los de GMT) empiezan de la misma manera, con un gato-exclamación (#!), donde este informa la ruta del shell que queremos usar para interpretar el script, en nuestro caso /bin/bash.
Ejemplo:
 #! /bin/bash
# Este es el inicio de un shell script


Fijando una variable

Fijar una variable es simple, por ejemplo, escriban en la terminal:
 MIVAR="mi variable"

Para ver la variable en la terminal, usamos:

 echo $MIVAR

Notar que no hay espacio alrededor del = cuando se fija una variable.

Scripts básicos

Tipea lo siguiente dentro de un nuevo archivo de texto, el cual llamaremos hola.sh

 #! /bin/bash
echo "Hola a todos"

Ahora en la terminal cambie los permisos al archivo para hacerlo ejecutable:

 chmod a+x hola.sh

Ahora ya puedes correr tu script, teclea en la terminal:

 ./hola.sh

Ahora introducimos una variable dentro de un script que estará en un archivo de texto que lo llamaremos (hola2.sh)

 #! /bin/bash
VAR="hola de nuevo"
echo $VAR

Cambia permisos y corre el script.
Usaremos en este curso comandos que aceptan parámetros para definir operaciones. Con esto tenemos scripts más flexibles que aquellos que definen los parámetros dentro del script.

Para usar argumentos, a cada variable pasada a nuestro script, se le asigna un número $1, $2, $3 etc. Por ejemplo, (argumentos.sh)

 #! /bin/bash
echo "El primer argumento es" $1
echo "El segundo argumento es" $2

Hace el script ejecutable y córrelo! Cuando el script muestra variables como $1 y $2 que no están definidas dentro del archivo de texto, entonces las puedes definir como tu quieras, así de la siguiente forma se corre este script:

 ./argumentos.sh 3 4

Es decir, en este caso la variable $1 tomará el valor de 3 y la variable $2 tomará el valor de 4. Puedes poner expresiones alfanuméricas como letras o palabras y serán asociadas a cada variable. Pero en este caso, como definiste sólo dos, por mas argumentos que pongas en la terminal, aparecerán sólo los dos primeros. Prueba lo siguiente:

 ./argumentos.sh hola mundo
./argumentos.sh hola mundo feliz

\textquestiondownVes? en este caso ``feliz'' no aparece, para que aparezca en el script tienes que definir otra variable $3. Nota que cada variable se diferencia de la otra por el espacio que pongas entre ellas al ejecutar el script.

Siempre los scripts requieren un cierto número de argumentos. Por ejemplo, si no recibe dos argumentos, el script argumentos2.sh alerta al usuario, y no corre si no recibe el número de parámetros que requiere:

#! /bin/bash

#Condicion que requiere el numero de argumentos sea 2:
if [ $# != 2 ]
then echo "ERROR: El uso correcto es: ./argumentos2.sh arg1 arg2"
exit
fi

#Si pasamos la condicion, corremos lo siguiente:
echo "El primer argumento es" $1
echo "El segundo argumento es" $2

Corre este script con y sin dos argumentos para ver la diferencia. Note que hay unos comentarios dentro del script (líneas que empiezan con #) y también un condicional [if ... then ... fi]

A veces, se requiere que el script pida algo al usario. Para eso usamos el comando read (hola3.sh)

 #! /bin/bash
echo "Cual es tu nombre?"
read VAR
echo "Hola "$VAR"!"

Aritmética en bash

Los shell scripts son usualmente usados para correr una serie de comandos con ciertos parámetros.
A veces un poco de aritmética es útil. Acá hay una lista de algunos operadores que se pueden usar:


Sintáxis Significado
a+b, a-b adición/sustracción
a*b, a/b multiplicación/división
a%b módulo, resto depués de la división
a**b exponencial


Por ejemplo, prueba los siguientes comandos:

 echo $[100+5]
echo $[100/3]
echo $[100%3]
echo $[2**4]

Note que el comando awk también puede hacer aritmética en bash:

 echo 100 3 | awk '{printf"%0.2f\n", $1/$2}'

Expresiones lógicas

El número de expresiones lógicas que pueden verificarse es muy grande, incluyendo operadores para cadenas de carácteres y números enteros.

Operadores de comparación numéricos

Operador Singnificado
-eq igual que
-ne no igual que
-gt mayor que
-ge mayor o igual que
-lt menor que
-le menor o igual que



Operadores de comparación de texto

Bash utiliza los comparadores habituales en matemáticas para comparar textos (mientras que para números utiliza los que se han visto anteriormente). Así la lista de comparadores es:

Operador Singnificado
= igual
!= no igual
> mayor que
> menor que



Loops

Si queremos repetir algo varias veces, podemos usar loops dentro de un script :

for

for elige un rango de variables, o una lista de archivos, y aplica comandos a cada uno de ellos. Por ejemplo, en el script for.sh imprimimos los números del 1 al 10 en el terminal.
#! /bin/bash
for x in {1..10}
do
echo $x
done

o si queremos hacer una copia de seguridad back up (copiar cada archivo de un directorio a un archivo .bak) podemos usar: (for1.sh)

 #! /bin/bash
for archivo in `ls -1`
do
cp $archivo $archivo.bak
done

while

El comando while ejecuta el loop de instrucciones situado entre do y done mientras se cumpla la condición especificada como parámetro en la llamada. El siguiente script muestra lo que hace el condicional while, donde se define la variable $ x=0$, y el condicional dice que muestre "$ x$" mientras éste sea menor que 12. El resultado será una sucesión desde 0 (valor inicial) hasta 11 (valor definido por while). Llamaremos a este script (while.sh)
#! /bin/bash

#Definiendo x igual a 0
x=0

#Definiendo el condicional que dice que muestre el
#numero x mientras este sea menor que 12
while [ $x -lt 12 ]
do
echo $x

#Aumentando x por 1 (para crear una sucesion de x ascendente
#para cada loop del while)
x=$[$x+1]

#Fin de condicion while
done

Condicionales

En todo entorno de programación es necesario automatizar la repetición de determinadas acciones un número fijo de veces o en función de que se cumpla o no una condición.

if

Este comando permite seleccionar entre algunas opciones, por ejemplo, el siguiente script (if.sh):
#! /bin/bash

#El script pide que ingreses tu edad:
echo "Ingrese su edad"
read edad

#Condicional que selecciona tu condicion laboral
#dependiendo del valor que asignes a la variable $edad
if [ $edad -ge 65 ]; then
echo "Si no te has jubilado, deberias hacerlo"
else
echo "Eres activo laboralmente"
fi

En el siguiente script que combina for, while e if vamos a encontrar todos los números primos que se encuentren dentro de una sucesión de números "x" (en este caso entre 2 y 10, porque el 1 no se considera primo). El método para hacerlo consiste en tomar los módulos (o resto) del número "x" dividido por todos los números que sean menores que él mismo; los números primos nunca van a tener un resto cero de esa división, así que de esa forma se pueden identificar. (primo.sh)

#! /bin/bash
#Corre un loop para x de 2 a 10 (ya que el 1 no se considera entre los
#numeros primos):
for x in {2..10}
do

#Define una variable $primo para ser igual a 1
primo=1

#Define y igual a 2
y=2

#Condicion para hacer el siguiente conjunto de instrucciones solo cuando
#y sea menor que x
while [ $y -lt $x ]
do

#Calcula el resto de la division de x/y
resto=$[$x%$y]

#Si el resto es cero para cualquier set de $x, $y cambia el variable $primo a cero
if [ $resto -eq 0 ]
then
primo=0
fi

#Aumenta el valor de y por 1
y=$[$y+1]
#Termina la condiccion de "while"
done

#Si todavia el valor de primo es 1. Es decir, para cada valor de $x, de todos los
#set de $x, $y que se calcularon en el while (mientras $y<$x), ninguno de ellos tuvo
#resto cero, entonces el numero $x es primo
if [ $primo -eq 1 ]
then
echo $x "es primo"
fi

#Termina el loop de "for"
done

Case

La sentencia case en bash, es similar a la sentencia switch en C, Matlab y Octave. Esta sentencia no es un lazo como for y while, es decir, no ejecuta un bloque de comandos n veces , en vez de eso, case chequea alguna condición y controla el flujo del programa.
Cuando trabajen en la sección de GMT, case será una útil herramienta.


Su estructura es la siguiente:

case $variable in
caso 1) bloque de comandos ;;
caso 2) bloque de comandos ;;
caso 3) bloque de comandos ;;
caso n) bloque de comandos ;;
esac


A continuación, un sencillo ejemplo que entrega el horario de clases según el día.

#! /bin/bash
clear
dia=`date +"%u"`
case $dia in
1) echo "09:00 - 12:00 -> Meteorologia Sinoptica , Sala Dgeo"
echo "16:00 - 17:00 -> Ingles , CFRD" ;;
2) echo "10:00 - 12:00 -> Estadistica , FM-204"
echo "17:00 - 20:00 -> Sismologia de volcanes , Sala Dgeo" ;;
3) echo "10:00 - 12:00 -> Metodos Matematicos de la Geofisica , FM-201"
echo "09:00 - 11:00 -> Modelacion de Tectonica , A-213"
echo "18:00 - 20:00 -> Linux, Scripts y GMT , FM-304" ;;
4) echo "11:00 - 12:00 -> Horario de consulta Linux, Scripts y GMT , Oficina Matt"
echo "09:00 - 11:00 -> Preparacion Fisica , Casa del Deporte" ;;
*) echo "Hoy no tengo clases !!" ;;
esac
echo

matt 2014-03-19