Resumen Scripts
Resumen Scripts
Si ya has practicado un poco con el shell bash, te habrás dado cuenta de que se
pueden hacer muchas cosas interesantes con él. Aunque hay veces, que para
conseguir determinado resultado necesitaremos introducir, por ejemplo, 3 o 4
comandos; o tenemos que evaluar una condición manualmente (por ejemplo, con ls
comprobamos manualmente si un archivo existe). Los scripts de shell nos dan la
posibilidad de automatizar series de comandos y evaluaciones de condiciones.
Aunque en principio esto puede resultar un tanto abstracto, vamos a verlo despacio
y con ejemplos. Si no has programado nunca, en este capítulo encontrarás el
aprendizaje del shellscripting en bash como una sencilla introducción a la
programación, que te ayudará a comprender después los fundamentos de otros
lenguajes de programación. No te preocupes, porque lo vamos a explicar todo de
forma sencilla y no te quedará ninguna duda.
Pues bien, vas a crear tu primer script bash. Para ello utilizaremos el editor vim, que
es la versión mejorada del editor vi. Si recordamos, un script era un archivo de texto
plano con comandos; así que haz vim miscript.sh y pon en él lo siguiente (lo
explicaremos detenidamente a continuación):
hacia la aplicación bash. Como más adelante tendrás tiempo de descubrir, hay otros
tipos de scripts (Perl, Python, PHP...) para los cuales deberemos indicar la
aplicación ayudante correspondiente.
Como ves, no importa que pongamos líneas en blanco, pues serán ignoradas.
Podemos ponerlas después de cada bloque de comandos que tengan cierta
relación, para dar claridad y legibilidad al conjunto de comandos del script.
Las dos siguientes líneas comienzan por el carácter #. En los scripts de bash, las
líneas que comienzan con este signo son ignoradas, y se llaman comentarios.
Podemos usarlas para explicar qué hace el grupo de comandos siguiente, de tal
forma que cuando editemos el script en el futuro nos sea más fácil descubrir qué es
lo que está haciendo en cada sitio; o podemos usarlos para dar cualquier otra
información importante de cara a la edición del archivo. Veremos más ejemplos de la
utilidad de los comentarios después.
Las dos últimas líneas son dos comandos, de los que luego serán ejecutados por
bash. Como sabemos, el comando echo saca por stdout (por defecto por pantalla)
lo que le pasemos como argumento, en este caso dos frases. Podemos añadir
cualquier comando normal de los que hemos visto, que será ejecutado normalmente.
Después escribiremos algunos scripts más complejos, para que te hagas una idea
de para qué pueden servirnos.
Como ves, todos los comandos del script han sido ejecutados. Aunque la forma más
frecuente de ejecutar scripts es, darles primero permisos de ejecución, como ya
sabemos del capítulo de usuarios, grupos y permisos:
2. Variables
Repasemos el ejemplo despacio. En primer lugar tenemos la línea que será siempre
la primera en nuestros scripts, y que ya conocemos, la que dice cuál es el programa
que ejecutará las instrucciones del script.
Siguiendo tenemos la asignación de algunas variables, esto es, estamos dando valor
a algunas variables que luego usaremos. Observa que entre el nombre y el valor,
NO HAY ESPACIOS, es variable=valor. Procura recordarlo. Ahora cada
variable tiene el valor que le hemos asignado. Podríamos cambiarlo simplemente de
la misma forma, pero poniendo otro valor distinto, que sobreescribiría a cualquiera
que tuviese antes la variable. Así, tercera=7 haría que el valor de la variable
tercera fuese de ahí en adelante 7.
A la variable frase le vamos a asignar una cadena de texto. Date cuenta de que
esta vez tampoco hay espacios en medio de la asignación y que EL TEXTO VA
SIEMPRE ENTRE COMILLAS, pudiendo ser simples o dobles. La estructura es
entonces variable="texto". En la línea siguiente, con el comando echo de
nuevo, podemos sacar por pantalla el texto que habíamos guardado en la variable.
Por último tenemos el comando exit. Este comando al final del script no es
especialmente útil, pero si pusiésemos cualquier cosa debajo de él ya no sería
ejecutada. Lo usaremos después cuando queramos que "si se da tal condición,
entonces que el programa (script) termine".
3. Comandos posibles
Una duda que puede surgir es... ¿qué comandos puedo escribir en mis scripts?
¿Tengo alguna limitación?
De aquí otra de las bondades de los scripts en bash: todos los comandos que
escribiremos en bash pueden escribirse en un script de bash; esto incluye cualquier
programa, redirecciones de entrada o salida, pipes, etc. Usando comandos del
sistema, podemos hacer que nuestros scripts hagan casi cualquier cosa que
nosotros queramos, y que se comporten como si de complejísimos programas se
trataran. Esto es, para borrar un fichero dentro de un script, simplemente
necesitamos usar el comando rm, sin preocuparnos por cómo funciona rm
internamente. Con los comandos que ahora conocemos, nuestros scripts podrán:
listar ficheros o directorios, borrar, despreciar salidas, buscar en cadenas de texto,
pedir datos al usuario e interpretarlos...
Hacer notar una cosa. Cuando una de nuestras variables sea el argumento de un
programa, y si lo llamamos con muchos argumentos, es muy conveniente para evitar
errores extraños, entrecomillar la variable:
Todavía hay muchos comandos que no conocemos, pero cuando aprendas algunos
nuevos, recuerda que pueden servir para dar funcionalidades extra a tus scripts.
En el shell bash (y por extensión, en nuestros scripts) el valor de retorno del último
programa o comando ejecutado queda almacenado en la variable especial $?.
Veamos un ejemplo:
En el primer caso, pedimos a ls que liste un archivo existente. Lo lista con éxito y
por tanto el valor de retorno vale cero. En el segundo caso le pedimos que liste un
archivo inexistente. Como eso no es posible, el comando no termina con éxito y el
valor de retorno es distinto de cero (en este caso 2).
Por último tenemos la variable especial $#. Esta variable contiene un número entero,
que vale el número de parámetros que pasamos al script sin contar $0. Ejecutemos
el script de dos formas distintas para comprender todo esto:
Estas dos ejecuciones han debido servir para ilustrar cómo funcionan estas variables
especiales para recibir parámetros en nuestros scripts. Conforme sigamos
aprendiendo veremos cómo podemos hacer que nuestro script se comporte de una
forma u otra dependiendo de los parámetros que se le pasen. Cada vez más,
nuestros scripts se irán pareciendo a programas "de los buenos".
Todavía hay más... puede que no se te ocurra cómo listar todos los parámetros que
se le pasen al script, sean cuantos sean. El comando shift nos da la solución. Hay
algunas cosas que debemos saber antes de poder usar shift para listar los
parámetros pasados a un script. No obstante, hay un ejemplo en “Funciones”, que
aplica tanto a funciones como al script en sí mismo.
Variable de proceso
Hay que recordar que existe la variable especial $! . Esta variable contiene el ID de
proceso del último comando ejecutado.
6. Evaluación de condiciones
Muchas veces nos será necesario hacer que nuestro script se comporte de una
forma u otra según el usuario introduzca uno u otro argumento, o según una variable
tenga tal o cual valor. En esta sección pasamos a ver los comandos y estructuras
que nos permiten hacer esto.
Primero, 7 -eq 7 es lo que se conoce como expresión. De esta forma tan peculiar
al principio le decimos a test que compruebe si 7 es igual a 7 (-eq, abreviatura de
'equals', 'es igual a'). Así que ese primer comando quiere decir: ¿Es 7 igual a 7?
Como ves, test no ha producido ninguna salida por la pantalla, sin embargo, si
comprobamos su valor de retorno, vemos que es cero (0), lo cual indica que la
expresión es verdadera, 7 es igual a 7, efectivamente.
y que repetimos todo lo anterior, pero en vez de usar 7 y 8, usamos las variables $a
y $b. No hay cambios, test reemplaza las variables por su valor y después efectúa
la comprobación, siendo el resultado final el mismo.
Para no tener que aprender de memoria la forma en que hay que introducirle las
expresiones a test, puedes consultar las páginas del manual: man test
Puedes moverte con las flechas de dirección y volver al shell pulsando la tecla q.
Entonces, para ver cómo y qué otras cosas se pueden evaluar con test, es muy
recomendable seguir el consejo arriba expuesto.
Existe además otra forma de llamar a test que no es con el comando, y que en
nuestros scripts puede ayudarnos a que con un sólo golpe de vista nos demos
cuenta de qué es la expresión que se evalúa. Esta otra forma consiste en poner
entre corchetes (y con espacio) la expresión a evaluar:
Hemos visto cómo evaluar condiciones con test. Con la ayuda de las estructuras
condicionales que crearemos con if y lo que ya hemos aprendido, podremos por fin
hacer que nuestros scripts se comporten de una forma u otra según las condiciones
que nosotros especifiquemos.
Este es el modelo más general con todas las opciones posibles. Si el valor de
retorno de EXPRESION1 es cero, las líneas de comandos de "Bloque 1" serán
ejecutadas. El resto del bloque if será ignorado en ese caso.
En este sencillo ejemplo hacemos que el usuario introduzca un número que queda
guardado en la variable $input. Dependiendo de si el número es menor, igual o
mayor que 21, el script se comporta de una forma u otra (podemos añadir más
líneas de comandos después de los echo's que aparecen ahí). Si el usuario no
introduce nada o introduce una cadena de texto, lo que hay tras else es lo que será
ejecutado, pues ninguna de las condiciones anteriores se cumple.
Date cuenta que en las expresiones entre corchetes podrían haberse sustituidos
estos corchetes por test.
De todos modos, los elif y los else son opcionales, podemos crear una estructura
condicional sin ellos si no los necesitamos. Como muestra, el siguiente ejemplo:
En primer lugar comprobamos que nos han pasado dos argumentos: el fichero
donde buscar y la cadena de búsqueda. Si no es así, le indicamos al usuario cómo
debe ejecutar el script y salimos.
Ni que decir tiene que eso es posible hacerlo con if, y elseif, pero existe otra
forma más eficiente y cómoda de hacer esto: con la estructura case. Se usa como
sigue:
valor1 y valor2 son valores que nosotros esperamos que la variable pueda
contener, y Bloque 1 y Bloque 2 son los bloques de comandos con lo que
queremos que se haga en cada caso. Podemos poner tantos valores reconocibles
como queramos. Los puntos son precisamente para indicar esto. El * (asterisco) es
un comodín exactamente igual que hacíamos moviéndonos entre directorios en
capítulos anteriores, cualquier cosa que no haya coincidido en alguna de las de
arriba coincidirá aquí. Esto es completamente opcional. No obstante, en el ejemplo
siguiente te darás cuenta de su utilidad.
En este ejemplo se hace que las opciones tengan que ir precedidas de un doble
guión en forma larga (la única que reconoceremos en este caso), de esta forma
damos a nuestro script un aspecto y un comportamiento más "profesional". Los
argumentos no se suelen hacer preceder de ningún signo; aunque todo esto puedes
ponerlo como tú prefieras, lo importante es que aprecies cómo funciona este tipo de
estructura condicional.
Con exit salimos del script, haciendo que el valor devuelto sea 0 (éxito) o 1 (error)
según los parámetros fueran reconocidos o no.
9. Bucles
De los propósitos explicados anteriormente a solucionar por los bucles, for viene a
solucionar el segundo. Veamos algunos ejemplos:
En primer lugar apreciamos que todo lo que se puede hacer en un script también se
puede hacer en bash. La estructura de for es la siguiente:
comando 1
comando 2
# y así los que queramos
done
Con este bucle lo que conseguimos es: comando 1, comando 2, etc. se ejecutan
tantas veces como elementos haya en LISTA. Para la primera vez, $nombre_var
valdrá el primer elemento de la lista, para la segunda vez que se ejecuten los
LISTA puede ser una lista de archivos dada implícitamente. Más concretamente,
podemos usar los wildcards que ya conocemos para referirnos a varios archivos con
un nombre parecido:
El elemento LISTA del bucle for, puede ser un comando entrecomillado con
comillas laterales; un comando tal que su salida sea una lista de elementos. Así,
sería lo mismo:
for i in *; do
que:
for i in `ls`; do
El otro tipo de bucle posible en bash-scripting es el bucle while. Este bucle viene a
cumplir con el propósito de "quiero que se haga esto mientras que se dé esta
condición". Su estructura es la siguiente:
# Comandos a ejecutar
done
Como ya sabemos usar el bucle anterior, este lo entenderemos con algunos pocos
ejemplos:
Tanto en el bucle for como en el while, podemos usar break para indicar que
queremos salir del bucle en cualquier momento:
Ten en cuenta que en bash scripting, usando la notación $[ ] para hacer cálculos
sólo podemos usar números enteros.