8.-SHELL SCRIPTS

Como se vió al principio del curso, la shell nos permite acceder al kernel del sistema operativo. La shell en reaildad lo que hace es interpretar la línea de comandos y ejecutar los programas que
ésta indica. Sin embargo, además de leer la línea de comandos, también puede ejecutar los comandos que se encuentren en un fichero. Cualquier comando que pueda ser tecleado en la línea de
comandos puede ser incluido en un fichero al que se le denomina como shell script o shell program.

Un shell script es un fichero donde hemos introducido cualquier comando que se puede ejecutar en la shell. Se pueden incluir comandos UNIX, utilidades, emplear pipes, redireccionar
entradas y salidas, definir y utilizar variables, además del uso de una serie de comandos UNIX creados para ser usados fundamentalmente en los shell scripts, como son condicionales y
comandos para controlar el flujo del programa.

Si queremos poner comentarios en nuestros scripts, lo hacemos con el símbolo #

8.1.-Declaración de variables

Para definir variables se utilizan las palabras reservadas set y setenv seguidas de la variable que queramos definir. Set sirve para declarar variables locales y setenv para variables de entorno. Variables del mismo tipo pueden declararse juntas al principio del programa (Ej: set name,  name1). Antes de darle un valor a una variable, ésta debe estar definida.

1.1- Asignar números a variables ->Para asignar un valor numérico a una variable se utiliza @ variable = valor, dejando los espacios.
1.2.- Asignar palabras a variables -> Se utiliza set name = "Esto es una frase"
1.3.- Asignar variables a otras variables -> Se utiliza el símbolo del dollar set name1 = $name
1.4.- Crear arrays ->  Para definir arrays, se hace también con set. Los datos que componen el array hay que separarlos por espacios y deben ir encerrados entre paréntesis.
Ej: set direction = (Norte Sur Este Oeste)
     echo $direction
     echo $direction[1]
     echo $direction[1-3]

8.2.- Interacción con el usuario

8.2.1.- Leer un valor desde teclado -> Para introducir una palabra desde teclado se utiliza $<, y para un número  es similar.
            Ej: #!/bin/csh
             clear
             echo " "
             echo " Cual es tu nombre?:"
             set nombre = $<
             echo "Y tu edad?:"
             @ edad = $<
8.2.2- Escribir en un fichero -> Para escribir algo en un fichero se utiliza el pipe >. Si el fichero ya existe y se quiere añadir algo al final, se utiliza >>.
           Ej: #!/bin/csh
             clear
             echo " "
             echo " Cual es tu nombre?:"
             set nombre = $<
              echo "Tu nombre es:" $nombre > fichero.dat
             echo "Y tu edad?:"
             @ edad = $<
              echo "Tienes" $edad "años" >> fichero.dat

EJERCICIO:

Hacer un pequeño script que pregunte varios datos, los incluya en un fichero y muestre el contenido del fichero por pantalla.
#!/bin/csh
echo "  "
echo "Nombre:"
set nombre = $<
echo "Cual es tu número de teléfono?"
@ telefono = $<
echo "Cual es tu edad?"
@ edad = $<
echo $nombre $telefono $edad >> agenda.dat
cat agenda
 

8.3.- Operaciones

8.3.1- Operadores matemáticos
 
Operador Operación
         + Suma dos números
         - Resta dos números
         * Multiplica
         / Divide 
         % Divide y saca el resto 

Ej: @ a = 47
      @ b = 32
      @ suma = $a + $b
      @ resta = $a - $b
      @ producto = $a * $b
      @ divide = $a / $b
      @ resto = $a % $b

8.3.2.- Operadores lógicos
 
 
Operador Operación
          !    Operador NO
          &&    Operador Y
          ||    Operador O

8.3.3.- Operadores de comparación
 
 
Operador Operación
        == Igual a
        != No igual a
         > Mayor que
         >= Mayor o igual a
         < Menor que
         <= Menor o igual que

 8.4.-Condicionales

La instrucción para el condicional es if. Es interesante utilizar el condicional cuando queremos que nuestro programa  chequee si una condición es verdadera o falsa. La forma del condicional es la siguiente:

if (condición) then
  instrucción
end if

Si queremos ejecutar diferentes instrucciones de pendiendo de si la condición es verdadera o falsa, se utiliza el comando else

if (condición) then
   instrucción1
else
   instrucción 2
endif

También podemos hacer condionales con varias condiciones

if (condición1) then
   instrucción1
else if (condición2) then
   instrucción2
endif
endif

EJERCICIO

Hacer un pequeño script que nos pregunte la edad y dependiiendo de la edad que tengamos escriba una cosa u otra
 

#!/bin/csh
echo " "
echo " Cuantos años tienes?"
@ edad = $<
if ($edad < 18) then
  echo "Eres un poco joven para estar aqui"
else if ($edad >= 18 ) then
  if ($edad > 65) then
    echo "Eres un poco mayor para estar aqui"
  else
    echo " Cual es tu nombre?"
    set nombre = "$<"
    echo " "
    echo "Hola" $nombre
    echo " "
  endif
endif
endif


8.5.- SWITCH

Cuando se tienen muchos condicionales es conveniente utilizar lo que se llama el switch. La forma de utilizarlo es la siguiente:

switch (Variable)
   case valor1:
          Instrucción1
          breaksw
    case valor2:
          Instrucción2
          breaksw
endsw

EJERCICIO

Escribir un pequeño menú de opciones:

#!/bin/csh
echo "1. Leer un número de la agenda"
echo "2. Introducir un nuevo número"
echo " "
echo "Q quit"
echo " "
echo "Opción:"
set elecci = $<
switch ($elecci)
   case "1":
       echo "Quieres leer un número de teléfono"
       breaksw
   case "2":
       echo "Quieres introducir un nuevo número"
       breaksw
   case "Q":
       exit 0
       breaksw
   case "q":
       exit 0
       breaksw
   default:
       echo "Has elegido mal. Eso no era una opción"
       breaksw
endsw
 

8.6.- El WHILE loop

El While loop tiene la siguiente sintaxis:
while (condition)
     Instruction
end

El while loop se utiliza cuando queremos que nuestro programa repita unas intrucción/es. Supongamos que queremos hacer un menú como el anterior, pero sólo salir del programa cuando queramos nosotros, no una vez hayamos seleccionado una opción. Para ello utilizamos el while.

Ej:
#!/bin/csh
set flag = "1"
while ($flag == "1")
   echo " "
   echo "1. Leer un número de la agenda"
   echo "2. Introducir un nuevo número"
   echo " "
   echo "Q quit"
   echo " "
   echo "Opción:"
   set elecci = $<
   switch ($elecci)
      case "1":
          echo "Quieres leer un número de teléfono"
          breaksw
      case "2":
          echo "Quieres introducir un nuevo número"
          breaksw
      case "Q":
          set flag = "0"
          breaksw
      case "q":
          set flag = "0"
          breaksw
      default:
          echo "Has elegido mal. Eso no era una opción. Elige de nuevo"
          breaksw
    endsw
end
 

EJERCICIO: Supongamos que tenemos un programa y queremos que si en un lugar determinado hay un error nos lo diga, pero asegurándonos de que leeremos el mensage en pantalla. Hacer un pequeño script que nos escriba en pantalla que ha habido un error, espere unos segundo y vuelva a escribir el mensage.

#!/bin/csh
set j = 0
clear
while ($j < 20)
    @ i = 0
    while ($i < 2)
  echo " "
         echo "=============== "
         echo " Hay un ERROR!  "
         echo "=============== "
         echo " "
         @ i = $i + 1
    end
    @ k = 0
    while ($k < 5000)
  @ k = $k + 1
    end
    @ j = $j + 1
end
 

8.7.- El FOREACH loop

Imagina que quieres escribir una misma carta a varias personas. El comando foreach se utiliza para este tipo de situaciones.
La sintaxis es la siguiente:

foreach variable (lista)
     Instruccion
end

Ej:
#!/bin/csh                                                                      #!/bin/csh
set amigo                                                                     set amigo
foreach amigo (Antonio Angel Monica)                 foreach amigo ("Antonio Manuel" "Angel Garcia"  "Monica")
   echo " "                                                                        echo " "
   echo "Hola $amigo"                                                  echo "Hola $amigo"
   echo " "                                                                        echo " "
end                                                                                end
 

8.8.- Salida de bucles

Los bucles seguirán ejecutándose hasta que la condición sea falsa. Para romper un bucle antes de que la condición cambie, podemos utilizar el break

Ej:

#!/bin/csh
set flag = "go"
while ($flag == "go")
   echo "Nombre o teclea STOP para salir"
   set amigo = $<
   if ($amigo == "stop") then
      break
   endif
   if ($amigo == "STOP") then
      break
   endif
   echo " "
   echo " Hola $amigo"
   echo " "
end
echo "Hasta luego"

Para no salir del bucle, pero que no se ejecuetn las instrucciones que siguen, se utiliza continue, que hace que el programa vuelva al principio del bucle.

EJERCICIO:
Hacer un script que pregunte el nombre y si el nombre es el de una persona que uno no quiere, pues pase de él y vuelva a prguntar el nombre:

#!/bin/csh
set flag = "go"
while ($flag == "go")
   echo "Nombre o teclea STOP para salir"
   set amigo = $<
   if ($amigo == "stop") then
      break
   endif
   if ($amigo == "STOP") then
      break
   endif
   if ($amigo == "Juan") then
      continue
   endif
   echo " "
   echo " Hola $amigo"
   echo " "
end
echo "Hasta luego"
 

8.9.- Subprogramas

En muchas ocasiones es útil escribir nuestros scripts utlizando subprogramas. Un conjunto de subprogramas formarán un programa más complejo.  Esto facilitará la compresión del script y será mucho más cómodo corregir  los subprogramas con errores, o adaptarlos a nuevos scripts.

Antes de empezar a escribir un script es útil construir un diagrama de flujo de él. El diagrama de flujo nos va a dar una idea de como organizar y oredenar nuestros subprogramas.  Supongamos que queremos hacer una pequeña agenda de teléfonos:

Ej:                                                       Menú
                                                                de
                                                          Opciones
 

Buscar un                   Añadir un nuevo         Modificar la        Imprimir la
teléfono                          teléfono                     agenda                 agenda
 

                                                         Salir del programa
 
 
 

8.9.1.- Como hacer los subprogramas

Podemos mencionar algunas reglas para escribir subprogramas:

1. Las instrucciones deben aparecer en el subprograma en el orden en el que queramos que nuestro programa las ejecute.

2. Cada subprograma debe ser grabado en un fichero diferente.

3. Cada subprograma debe ser convertido a un fichero ejecutable utilizando el comando chmod.

4. El subprograma debe ser probado antes de incluirlo en el programa, y no incluirlo hasta que hayamos solucionado todos los problemas que pueda tener.

5. Es conveninte asignar un nombre adecuado al subprograma, que nos de idea de lo que hace.
 

Ejercicio: Hacer una pequeña agenda de telefonos utilizando subrutinas.

#!/bin/csh
set flag = "go"
while ($flag == "go")
 echo " "
 echo " "
 echo " AGENDA DE TELEFONOS"
 echo " "
 echo "1. Buscar un numero de telefono"
 echo "2. Añadir un numero de telefono"
 echo "3. Modificar un numero ya existente"
 echo "4. Mostrar la agenda de telefonos"
 echo "5. Salir"
 echo " "
 set eleccion = $<
 switch ($eleccion)
      case "1":
               buscartel
               breaksw
      case "2":
               metertel
        breaksw
      case "3":
               modiftel
        breaksw
      case "4":
               mostragen
        breaksw
      case "5":
               set flag = "exit"
        breaksw
             default:
               echo "Te has equivocado. Vuelve a elegir."
        breaksw
        endsw
end
 

8.10.- Busca de información con AWK

El comando o utilidad AWK es la más popular herramienta entre los programadores para hacer búsquedas dentro de bases de datos. Este comando consta de dos partes:
(a) El patrón de búsqueda
(b) Los datos que queremos mostrar

La información que buscamos en una base de datos es lo que se denomina expresión de búsqueda. La expresión de búsqueda le dice al ordenador como identificar las columnas en la base de datos que queremos ver. La expresión de búsqueda debe aparecer al principio del comando AWK y debe estar encerrada entre barras inclinadas a la derecha ( slash / ).

Ej:

awk '/galaxia/ {print $1, $2, $3}' galaxias.dat -> Buscará dentro del fichero galaxias.dat la palabra galaxia y escribirá en pantalla las tres primeras columnas de las líneas en la que aparezca esta palabra.

Si queremos buscar pero sólo tomando el principio de la línea, no todas las columnas de una misma línea, utilizaremos el caracter ^ al principio de la expresión de búsqueda

awk '/^galaxia/ {print $1, $2, $3}' galaxias.dat

También podemos especificar la columna en la que queremos realizar la búsqueda:

awk '$11 ~ /^galaxia*/ {print $4,$5}' galaxias.dat

$11 representa la columna en la que estamos haciendo la búsqueda.
La tilde ( ~ ) le dice al ordenador que estamos haciendo una búsqueda. Es igual que el operador == que utilizamos con if.
El caracter ( ^ ) le dice al ordenador que haga la búsqueda al principio de la columna.
El asterisco ( * ) le dice al ordenador que no importa que haya otros caracteres en esa columna junto con los que buscamos.

También podemos decirle al ordenador que busque las columnas que no presenten una serie de caracteres. Lo hacemos anteponiendo a la tilde ( ~ ) la admiracion ( !~ ):

awk '$11 !~ /^galaxia*/ {print $4,$5}' galaxias.dat