Variables en Bash Scripting (Parte III)

27 Abr

Cuarta publicación del curso de Bash Scripting.

Variables Locales

Las variables locales son aquellas que pertenecen a un bloque en específico o a una función y por lo tanto no son visibles fuera de ese bloque, una variable dentro de una función no es visible al resto de código en el script hasta que dicha función se ha llamado (esto se verá en el capítulo dedicado a funciones), sin embargo, podemos usar las palabras claves local y declare para que las variables no sean visibles sino solamente en el bloque en que han sido declaradas.

Una función es un subprograma que lleva a cabo una tarea específica y devuelve un valor.

Variables de Entorno

Las variables de entorno son aquellas que afectan el comportamiento de la shell, son relevantes pues pueden verse como “variables globales” para cualquier script, por lo que pueden ser utilizadas en cualquier momento por un script.

El comando env permite ver las variables de entorno.

Las variables de entorno pueden definirse en scripts que se ejecutan al iniciar sesión en un sistema Unix, por ejemplo, el archivo .bashrc ubicado en nuestro directorio home. Esto significa que si declaramos una variable de entorno por fuera de estos scripts, esa variable no estará disponible cuando el sistema vuelva a arrancar.

Para conocer más acerca de las variables de entorno o ambiente, es recomendable leer el capítulo tres de “Libro Rojo de GNU/Linux”

Variables Internas

Afectan el comportamiento de los scripts en Bash.

Los nombres de las variables internas y de entorno generalmente aparecen en mayúscula, por lo que para los scripts se recomienda utilizar nombres en minúscula.

Para ver el contenido de una variable interna o de entorno, se usa el caracter $ al igual que con las variables que nosotros mismos definamos:

null   
echo $BASH_VERSION

Lo anterior mostraría la versión del intérprete o shell que tengamos instalados; la variable $$ también está disponible como una variable interna, es la misma variable $BASHPID, pero no debe confundirse con la que se imprime en un script, la shell también es un proceso, por lo que si se imprime $$ directamente en el intérprete, se obtiene el PID del intérprete, y si se imprime desde un script, se obtiene el PID de dicho script.

Una lista inicial de variables internas y de entorno, puede verse en: http://wiki.bash-hackers.org/scripting/basics

Conclusiones

Con lo visto en la primera parte es suficiente para trabajar con variables, pero se han dado las demás explicaciones para no extendernos tanto cuando se haga uso de los demás detalles mencionados, sino que se sepa a qué se hace referencia.

Las variables internas y de entorno juegan un papel muy importante en la programación de scripts de Bash, pues dichos scripts interactuan de forma directa con el sistema, y estas variables definen el comportamiento del sistema.

Anotaciones

En esta entrega tardía, aprovecharemos para hablar un poco más acerca de las cadenas en Bash Scripting: El manejo de cadenas es una herramienta necesaria, pues en muchos casos se deben procesar cadenas de caracteres para obtener la información y actuar según lo obtenido.

Para recuperar el valor de una variable, podemos usar ${var} en vez de la forma simplificada $var.

Cada vez que nos encontramos con una cadena, hay cosas que es muy probable que nos preguntemos: ¿Cuál es la longitud de la cadena?, ¿Cómo obtengo una subcadena?, esto es lo que responderemos.

null   
#!/bin/bash
 
var="Super cadena de caracteres"
echo La longitud de la cadena en \$var es ${#var}.
 
exit $?
La longitud de la cadena en $var es 26.

Para obtener subcadenas en un script de Bash, podemos usar slicing, el cual es un proceso que consiste en la extracción de elementos de la cadena, viendo cada caracter como un elemento. Veamos cómo funciona a través de algunos ejemplos:

null   
#!/bin/bash
 
var="Super cadena de caracteres"
echo ${var:5}
 
exit $?

Estamos usando el formato ${cadena:posicion}, esto devuelve la cadena a partir de la posición:

cadena de caracteres

Si hubieramos colocado ${var:6}, en este caso se obtendría el mismo resultado debido a que los espacios iniciales no se imprimen. Veamos el siguiente ejemplo:

null   
#!/bin/bash
 
var="Super cadena de caracteres"
echo ${var:6:6}
 
exit $?

En este caso usamos ${cadena:posicion:longitud}, obtendremos una subcadena de “cadena”, desde la posición “posición”, pero no hasta el final como en el caso anterior, sino con longitud “longitud” en el caso de que sea menor que la longitud del resto de la cadena:

cadena

Es importante tener en cuenta, que la posición se empieza a contar desde cero, así, si necesitamos obtener los 10 primeros caracteres de una cadena escribiríamos ${cadena:0:10}.

Otra forma de obtener subcadenas, puede hacerse por medio de los caracteres # y %, los cuales ayudan a eliminar prefijos y sufijos. Con un ejemplo quedará más claro:

null   
#!/bin/bash
 
dir="/srv/www/dir/www/etc/httpd"
echo ${dir#*www}
echo ${dir%www*}
 
exit $?

Los caracteres # y % permiten usar expresiones regulares para obtener coincidencias en las cadenas; las expresiones regulares son una forma poderosa de procesar texto a partir de patrones encontrados en el mismo. El caracter # permite eliminar prefijos, en este caso se ha colocado el prefijo *www lo que concuerda con cualquier subcadena de texto que termine en www, pero elimina la subcadena más corta (elimina /srv/www, la subcadena /srv/www/dir/www también coincide, pero la primera es la más corta), si hubiésemos colocado simplemente www, no se hubiera eliminado nada pues www no se encuentra al principio de la cadena, de la misma forma funciona % pero eliminando sufijos, por eso utilizamos www*, para que elimine cualquier subcadena que empiece con www hasta llegar al final, también se elimina la subcadena más corta (elimina www/etc/httpd, la subcadena www/dir/www/etc/httpd también coincide con el patrón colocado), la salida puede terminar de aclarar las dudas:


/dir/www/etc/httpd
/srv/www/dir/

Ahora supongamos que queremos eliminar precisamente las ocurrencias más largas, esto se realizaría de la siguiente manera:

null   
#!/bin/bash
 
dir="/srv/www/dir/www/etc/httpd"
echo ${dir##*www}
echo ${dir%%www*}
 
exit $?

Nótese el uso doble de cada caracter, en este caso la salida sería:


/etc/httpd
/srv/

Hace falta bastante práctica para manejar muy bien las expresiones regulares, por lo que se tiene en cuenta para un próximo curso, ya veremos cómo resulta todo.

Con lo mostrado se responden las preguntas que nos realizamos, sin embargo, esta vez queremos ir más allá. Bash nos permite realizar sustituciones de forma directa:

null   
#!/bin/bash
 
str="La casa sobre la mesa de la casa"
echo ${str/casa/taza}
 
exit $?

Lo que buscamos es reemplazar la primera ocurrencia de la palabra casa, por la palabra taza; nuevamente, el uso de expresiones regulares le da demasiada fuerza a este proceso y lleva la automatización de procesamiento de texto a niveles insospechados.

La taza sobre la mesa de la casa
Los caracteres # y % también pueden ser usados para sustituir prefijos y sufijos.
La herramienta sed es una forma mucho más completa de procesar texto pues incluye la facilidad descrita y demasiadas cosas más.

Ya hemos mencionado con anterioridad que cuando utilizamos una variable a la que no se le ha asignado valor alguno, no obtenemos ningún error, sino un valor nulo, veamos algunas facilidades para las variables con respecto a este aspecto:

null   
#!/bin/bash
 
echo ${var:-defecto}
 
var="Un valor"
echo ${var:-defecto}
 
exit $?

defecto
Un valor

Podemos notar que a una variable se le puede asignar un valor por defecto para cuando su contenido es nulo, esto quiere decir que si hubiésemos hecho var=””, entonces hubieramos obtenido “defecto” dos veces. En el siguiente ejemplo, vamos a asignar un valor por defecto a una variable y dicho valor no podrá cambiarse siempre y cuando la variable sea nula:

null   
#!/bin/bash
 
#var=""
 
echo ${var:="Valor 01"}
echo ${var:="Valor 02"}
 
var="Valor 03"
echo ${var:="Valor 04"}
 
exit $?

La línea comentada podría descomentarse y se obtendría el mismo resultado, cuando asignamos un valor diferente de nulo a “var”, la línea siguiente no surte efecto. Nótese también que la línea que tiene la cadena “Valor 02” no modifica la variable:


Valor 01
Valor 01
Valor 03

Podemos mostrar un error cada vez que tratemos de usar una variable nula, es decir, si aun no ha sido declarada:

null   
#!/bin/bash
 
echo ${var?}
 
exit $?
strings.bash: línea 3: var: parámetro nulo o no establecido

Personalización del mensaje de error:

null   
#!/bin/bash
 
echo ${var?"La variable \$var es nula"}
 
exit $?
strings.bash: línea 3: var: La variable $var es nula

La variable continua siendo nula si es declarada como tal:

null   
#!/bin/bash
 
var=""
echo ${var?"La variable \$var es nula"}
 
exit $?
strings.bash: línea 4: var: La variable $var es nula

Esto obliga a que debemos usar dicha variable con un valor diferente de nulo:

null   
#!/bin/bash
 
var="Mi valor"
echo ${var?"La variable \$var es nula"}
 
exit $?
Mi valor

Para terminar con los strings veamos lo siguiente, si una variable ya es diferente de nulo, podemos asignarle un valor alternativo:

null   
#!/bin/bash
 
echo ${var:+"Alterno"}
 
var=""
echo ${var:+"Alterno"}
 
var="Mi contenido"
echo ${var:+"Alterno"}
 
exit $?
En cada caso podemos dejar de usar los dos puntos, para este último caso, por ejemplo, podemos usar “+” en vez de “:+“.

Después de todo lo visto la salida es evidente. Para terminar, veamos la siguiente facilidad que nos permite ver el nombre de las variables internas que cumplen con cierto patrón:

null   
#!/bin/bash
 
Buho="Ojón"
echo ${!B*}
 
exit $?

Imprime todas las variables que comiencen con B:


BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION Buho

Esperamos que esta lluvia de detalles sea de ayuda en algún momento, son casos de poca utilidad pues su uso no es muy frecuente; para no alargar más estas anotaciones, hablaremos de la declaración de variables por medio de local y declare a través de ejemplos en unas próximas anotaciones.

Acerca del autor

Christian Gutierrez ha escrito 22 publicaciones en este blog.

Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why. – Anonymous Developer

Un comentario a “Variables en Bash Scripting (Parte III)”