Make your own free website on Tripod.com

Escribir Programas para el Shell

Además de usar el shell para ejecutar comandos, puedes usar su lenguaje de programación para escribir tus propios comandos o programas. Puedes poner comandos en el fichero (conocido como shell script) y después ejecutar el fichero como un comando o programa.

EL Bourne shell (sh) está disponible en todos los sistemas UNIX. Los scripts del Bourne shell también pueden trabajar bajo el Bourne Again Shell (bash). Los shells C y TC usan un lenguaje de programación similar al lenguaje C.

Sentencias para el Control del flujo del programa

Las estructuras de control de flujo del programa que tenemos disponibles cuando programamos en shell son el if, case, while, for y until. Además, veremos algunas órdenes especiales y algunas construcciones un poco más raras, que sirven también para controlar el curso de los acontecimientos.

Estructura if

La estructura if tiene una sintaxis algo inusual, porque necesita la palabra then, pero en la línea siguiente a donde está el if y la condición. Es un if bastante versátil, ya que permite cláusulas elif (else if) y else. La palabra para indicar el fin de la estructura if es la palabra fi (if al revés). La cláusula elif, es parecida al else, aunque necesita una condición después. Para comprender mejor el funcionamiento, veamos la siguiente equivalencia:

if [ condicion ]if [ condicion ]thenthen......elseelif [ condicion2 ]if [ condicion2 ]thenthen......fififi

Algunas personas, para hacer la sintaxis más clara, o al menos más parecida a otros lenguajes, como Pascal, escriben el if de la siguiente forma:

if [ condicion ]; thenfi

Para decidir qué ejecutar, la estructura if permite, además de una condición, el nombre de un programa. Lo que se hará entonces es ejecutar el programa con los parámetros dados, y dar como verdadero (y ejecutar lo que haya entre el if y el fi o el elif o el else) que el programa devuelva un cero.

En estos casos es muy útil la instrucción nula (:), ya que si lo que queremos es ejecutar un código si el programa va mal, entonces la única forma de hacerlo es la siguiente:

if ordenthen:# No hacemos nadaelsecodigo...fi

Como ejemplo tomaremos unas líneas que están en mi fichero ~/.bashrc:

if set | grep DISPLAY &>/dev/null; thenalias vi="vi -g"fi

Esto ejecuta la orden set, que da las variables de entorno. Las filtra para quedarnos sólo con la que contenga la variable $DISPLAY (si es que está), y manda toda la salida a un agujero negro (/dev/null). Esto se hace para comprobar el código de salida del grep, que devolverá verdadero si deja ``salir'' alguna línea. Es decir: si está definida la variable $DISPLAY, se entra a ejecutar el alias (en realidad, se entra si existe la variable $DISPLAY o si alguna variable tiene como contenido algo con la ristra DISPLAY, lo cual es bastante improbable. Hay una forma de afinar la condición, te lo dejo como ejercicio). Si el grep devuelve falso, no se ejecuta nada.

Condiciones particulares

Hay dos condiciones que son relativamente comunes, que son ejecutar un código si algo inmediatamente anterior ha ido bien, o justo lo contrario, ejecutarlo sólo si lo anterior ha ido mal.

Por ello, hay dos estructuras que nos permiten manejar estas situaciones de una forma más cómoda y limpia. Estas estructuras son && y ||. El && es el equivalente a la palabra reservada de Pascal and y || es el equivalente del or en Pascal.

La forma de entender qué produce cada estructura, es pensar que el intérprete sólo va a ejecutar lo estrictamente necesario para saber cómo termina la condición. Sabemos que false && cualquiercosa da falso, y que true || cualquiercosa da verdadero, así que eso es lo que va a hacer el intérprete: si utilizamos la estructura &&, ejecutará la primera instrucción, y sólo si va bien (si devuelve un cero) ejecutará la segunda, y análogamente con la estructura ||, el intérprete ejecutará la primera instrucción, y sólo ejecutará la segunda si la primera ha ido mal, es decir, si el valor de la condición total depende de lo que pase al ejecutar la segunda instrucción.

La estructura && puede utilizarse cuando ejecutemos una instrucción cuyo trabajo depende de que la primera haya ido bien, y la || puede ejecutarse para dar mensajes de error:

cd foo || echo "¡No puedo entrar en 'foo'!"

 

Estructura case

La estructura case del Bourne Shell y compatibles es una estructura parecida a la de Pascal: cuando entra en la estructura, sale cuando empiece la siguiente etiqueta (no así en C, en el que las etiquetas del case actúan como etiquetas de un JMP en ensamblador: una vez que entran en una etiqueta, no salen del case hasta que éste acaba completamente).

Las etiquetas pueden ser cualquier “expresión regular'', para indicar que termina el código de una etiqueta determinada, hay que poner al final de la última orden dos signos de punto y coma seguidos.

La estructura general del case es:

case valorinexpreg1)...ultimaorden1;;expreg2)...ultimaorden2;;...expregn)...ultimaordenn;;esac

Por ejemplo, si queremos comprobar una respuesta de sí o no, podemos hacer:

case $resp; ins*)echo "Has contestado sí (o algo parecido)"n*)echo "Has contestado no (o algo parecido)"*)echo "Has contestado alguna otra cosa"esac

 

  Estructura while

La estructura básica para construir bucles. La sintaxis es:

while ordendo...done

En orden podemos poner una orden normal y corriente (el bucle se ejecutaría mientras la orden devolviera un cero), o podríamos también poner una condición, con la orden test que por otra parte no deja de ser una orden como otra cualquiera.

Si quisiésemos estar seguros de que la contestación a la pregunta del ejemplo anterior era s o n, podríamos haber hecho lo siguiente:

while [ $resp != "s" -a $resp != "n" ]; doread respdone

Y justo debajo podríamos poner el case anterior, para comprobar cuál fue finalmente la respuesta.

Estructura for

Es otra de las estructuras importantes en los lenguajes de programación. Es más versátil que el equivalente de Pascal, pero menos que el equivalente de C.

Es una estructura que permite dos sintaxis: La primera, la del for más o menos tradicional (en los lenguajes interpretados), es decir, dar el nombre de una variable y los valores por los que tiene que “pasar'', es la siguiente:

for variable in expreg1 expreg2 ...expregndo...done

Hay una pequeña diferencia respecto a los bucles normales for, y ésta es que los valores por los que pasa la variable variable tenemos que especificarlos uno a uno (mediante expresiones regulares). Las expresiones regulares se intentarán hacer coincidir con los nombres de los ficheros del directorio actual.

Por ejemplo, si quisiéramos coger todos los ficheros normales y hacerles una sustitución con el sed, por ejemplo, una opción sería utilizar un bucle for. Por ejemplo, este bucle se utiliza para pasar texto de MS-DOS a texto UNIX:

for fichero in *.txt; dosed 's/^M//' $fichero >TEMPORALmv TEMPORAL $ficherodone

En este bucle, utiliza el sed yse sustituyen los caracteres de retorno de carro por nada, o sea, se borran. Esto convierte los ficheros de texto de MS-DOS a UNIX. Pero sed manda el resultado a la salida estándar, así que tenemos que dirigirlo a otro fichero (el TEMPORAL. Aquí suponemos que no existe ningún fichero llamado TEMPORAL en el directorio actual, o por lo menos que no es importante y lo podemos borrar). Una vez tenemos el resultado en el fichero TEMPORAL, simplemente lo movemos al fichero original, sobreescribiendo el fichero antiguo y poniendo la versión nueva, sin los caracteres de retorno de carro.

Estructura until

Esta estructura es parecida a la while, aunque la condición que se le da “al revés'', es decir, que el bucle se ejecuta mientras la condición a comprobar sea falsa, y termina cuando sea verdadera. Tiene una utilidad diferente que en los lenguajes de programación. Normalmente se utiliza en los lenguajes de alto nivel para forzar la ejecución del bucle al menos una vez, aunque la condición sea desde el principio verdadera. No se puede utilizar de esa manera en la programación en shell, porque la sintaxis tiene la condición al principio.

La sintaxis es como sigue:

until ordendo...done

 

Ejemplo:

Creación y ejecución de shell scripts simples

Para crear un shell script simple, debes poner líneas de comando en un fichero, ponle los permisos de acceso apropiados y después ejecuta el fichero.

EJEMPLO :

 Este es el contenido de un shell script llamado display : cat display# Este script displaya la fecha, hora, nombre de # usuario y directorio actualecho "Fecha y hora:"dateechoecho "Tu usuario es: `whoami` \\n"echo "Tu directorio actual es: \\c"pwd

Las primeras dos líneas que comienzan con una almohadilla (#) son comentarios y no son interpretadas por el shell. Usa comentarios para documentar tu shell script, te sorprenderá saber lo fácil que es olvidar lo que hacen tus propios programas.

Las backquotes (`) entre el comando whoami ilustran el uso de la sustitución de comandos.

- sustitución de comandos: para incluir la salida de un comando dentro de una línea de comandos de otro comando, encierra el comando cuya salida quieres incluir, entre backquotes (`)

- whoami : displaya el usuario actual

\\n es una opción del comando echo que dice al shell que añada un retorno de carro al final de la línea. \\c dice al shell que permanezca en la misma línea.

(si utilizas el shell bash, para que funcionen estas opciones tienes que poner echo -e )

Antes de usar el fichero como shell script debemos cambiar los permisos de acceso. Para dar permiso de ejecución al fichero deberemos usar el comando:

chmod u+rwx display

El +rwx después de la u te permiten leer, escribir y ejecutar el script, nadie mas tendrá permiso para hacerlo.

Para dar permiso a otros usuarios para leer y ejecutar el shell script se puede usar:

chmod go+rx display

 

Depuración de Shell scripts

Para ver donde se produce un error en un script usa el comando :

sh -x script argument

La opción -x del comando sh lista los comandos y sus argumentos que son ejecutados. Así puedes ver qué partes del script se han ejecutado cuando ocurre el error.

La opción -n del comando sh hace que no se ejecute ningún comando, solo chequea la sintaxis.

La opción -e en modo no interactivo, hace que si un comando falla se termine inmediatamente el script.

La opción -v imprime las líneas de entrada según son leídas
Pagina Principal | | ©2005 Universidad Tecnologica de Panama |