Cómo hacer ... (síntesis)
Presentación
Este capítulo propone soluciones para resolver diferentes problemáticas. Presentamos aquí las técnicas más utilizadas, la lista no es exhaustiva.
Información
Cuando los ejemplos de este capítulo se introducen en la línea de comandos, el símbolo $ representa el prompt del shell (PS1) y el símbolo > representa el prompt secundario del shell (PS2 - esperando la continuación del comando) (ver capítulo Configuración del entorno de trabajo - Variables de entorno).
En este capítulo, se utilizan expresiones extendidas del shell en varias ocasiones. Se recuerda que en bash, se debe habilitar la opción extglob para que las expresiones extendidas funcionen (ver capítulo Mecanismos esenciales del shell - Sustitución de nombres de archivos):
shopt -s extglob
Cuando los métodos de resolución presentadas funcionen solo para algunos shells, se especificarán estos últimos.
Plantillas de nombres de archivo
Objetivo
Trabajar con los nombres de archivo correspondientes a una plantilla.
Ejemplo
Listar los archivos con extensión .php o .sh.
Primer método
Con los caracteres de sustitución de nombres de archivo:
$ ls *.php *.sh
prog.php test.sh
(Ver capítulo Mecanismos esenciales del shell - Sustitución de nombres de archivos)
Segundo método (ksh, bash)
Con los caracteres de sustitución de nombres de archivo y la utilización de expresiones extendidas:
$ ls *.@(php|sh)
prog.php test.sh
(Ver capítulo Mecanismos esenciales del shell - Sustitución de nombres de archivos)
Tercer método
Utilización de expresiones regulares con grep:
$ ls | grep -E '(.php|.sh)$'
prog.php
test.sh
La opción -E del comando grep permite utilizar expresiones regulares extendidas (ver capítulo Expresiones regulares - Uso de expresiones regulares por comandos).
Verificar el código de retorno de un comando
Objetivo
Efectuar un proceso en función del código de retorno de un comando.
Ejemplo
Probar si el usuario Cristina está definido en el archivo /etc/passwd.
Primer método
Utilizando la estructura de control if:
$ if grep -q cristina /etc/passwd ; then
> echo "el usuario cristina existe"
> fi
Lo que también se puede escribir así:
$ grep -q cristina /etc/passwd
$ if [[ $? eq 0 ]] # ksh, bash (Bourne/posix: utilizar [ ] )
> then
> echo "El usuario cristina existe"
> fi
(Ver capítulo Las bases de la programación shell - Las estructuras de control)
Segundo método
Utilizando los operadores lógicos del shell (&&,||).
$ grep -q cristina /etc/passwd && echo "El usuario cristina
existe"
El usuario cristina existe
(Ver capítulo Las bases de la programación shell - Los operadores del shell)
Test de igualdad entre dos cadenas
Objetivo
Probar si una variable es por completo equivalente a un valor.
Ejemplo
La variable elección contiene el valor "sí".
Primer método (ksh, bash)
Uso del comando de test [[ ]]:
$ [[ $elección = sí ]] && echo '$elección vale sí'
(Ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Segundo método
Uso del comando de test [ ]:
$ [ "$elección" = sí ] && echo '$elección vale sí'
Al contrario que el comando [[ ]], el comando [ ] provoca un error si la expresión $elección está vacía y no entrecomillada (las comillas no impiden la sustitución de la variable).
(Ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Tercer método
Utilización de la estructura de control case:
$ case $elección in
> sí) echo '$elección vale sí';
> *) ...
>esac
(Ver capítulo Las bases de la programación shell - Las estructuras de control)
Cuarto método
Uso del comando expr y una expresión regular:
$ expr $elección : ‘sí$' >/dev/null && echo '$elección vale sí'
Con expr, el carácter ˆ está implícito...
Prueba de desigualdad entre dos cadenas
Objetivo
Verificar si una variable es diferente de un valor.
Ejemplo
La variable eleccion ¿es diferente del valor "sí"?
Primer método (ksh, bash)
Utilización del comando de verificación [[ ]]:
$ [[ $eleccion != sí ]] && echo '$eleccion es diferente de sí'
(ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Segundo método
Utilización del comando de verificación [ ]:
$ [ "$eleccion" != sí ] && echo '$eleccion es diferente de sí'
A diferencia del comando [[ ]], el comando [ ] genera un error si la expresión $eleccion está vacía y no tiene comillas (las comillas no impiden la sustitución de variables).
(ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Tercer método
Utilización del comando grep con la opción de negación -v y de una expresión regular:
$ echo $eleccion | grep -aqE '^sí$' && echo
'$eleccion es diferente de sí'
(ver capítulo Expresiones regulares - Uso de expresiones regulares por comandos)
Cuarto método
Utilización del comando awk y de una expresión regular:
$ echo $eleccion | awk '$0 !~ /^sí$/ {print "$eleccion...
Correspondencia de una variable respecto a un modelo
Objetivo
Comparar la correspondencia del contenido de una variable y una plantilla.
Ejemplo
Probar si la variable número contiene una serie de cifras, precedida de un posible signo.
Primer método (ksh, bash)
Uso del comando [[ ]] con expresiones extendidas:
$ [[ $nombre = ?([+-])+([0-9]) ]] && echo '$numero es un número'
(Ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Segundo método (ksh, bash)
Utilización de la estructura de control case con expresiones extendidas:
$ case $número in
> ?([+])+([0-9]) echo '$número es un número';
> ...
>esac
(Ver capítulo Las bases de la programación shell - Las estructuras de control).
Otros métodos
Los usuarios que trabajan con Bourne shell no pueden utilizar expresiones extendidas. Deberán recurrir a los métodos 4 a 6 de la sección Test de igualdad entre dos cadenas con las expresiones regulares adecuadas (expr, grep -E, awk).
No correspondencia de una variable respecto a un modelo
Objetivo
Comparar la no correspondencia entre el contenido de una variable y un modelo.
Ejemplo
Verificar que la variable cadena no contenga ninguna cifra.
Primer método (ksh, bash)
Utilización del comando [[ ]]:
$ [[ $cadena != *[0-9]* ]] && echo '$cadena no contiene ninguna cifra'
El modelo *[0-9]* representa una cadena que contiene al menos una cifra.
(ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Segundo método
Utilización del comando grep con opción de negación -v y de una expresión regular:
$ echo $cadena | grep -qEv '[0-9]' && echo
'$cadena no contiene ninguna cifra'
(ver capítulo Expresiones regulares - Uso de expresiones regulares por comandos)
Tercer método
Utilización del comando awk y de una expresión regular:
$ echo $cadena | awk '$0 !~ /[0-9]/ {print "$cadena no contiene
ninguna cifra "}'
(ver capítulo El lenguaje de programación awk)
Eliminar el comienzo o final de una cadena
Objetivo
Eliminar el final de una cadena de caracteres.
Ejemplo
Eliminar la extensión de un nombre de archivo.
Inicialización de la variable archivo
$ archivo=informe.docx
Primer método (ksh, bash)
Utilizar los caracteres de sustitución de variables:
$ echo ${archivo%.*}
Informe
El carácter % permite eliminar la parte más corta a la derecha correspondiente a .*.
(Ver capítulo Aspectos avanzados de la programación shell - Manipulación de variables)
Segundo método
Uso del comando expr:
$ expr $archivo: ‘\(.*\)\..*$'
informe
El comando expr devuelve la cadena que corresponde al paréntesis.
(Ver capítulo Expresiones regulares - Uso de expresiones regulares por comandos)
Tercer método
Uso del comando sed:
$ echo $Archivo | sed 's/\.[ˆ.]*$//'
informe
Se busca la parte de la extensión y se remplaza con vacío.
(Ver capítulo Expresiones regulares - Uso de expresiones regulares por comandos)
Cuarto método
Uso de la función sub de awk y una expresión regular:
$ echo $archivo | awk '{ sub(/\..+$/,"",$0); print $0 }'
informe
(Ver capítulo El lenguaje de programación awk - Funciones integradas)
Quinto método
Uso del comando basename:
$ basename $archivo .docx
informe
Este comando está dedicado...
Calcular la longitud de una cadena
Inicialización de la variable
$ palabra=arbol
Primer método (bash, ksh)
Utilizar la variable especial del ksh y bash:
$ echo "${#palabra}"
5
(ver capítulo Aspectos avanzados de la programación shell - Manipulación de variables)
Segundo método
Utilizar el comando wc:
$ echo -n "$palabra" | wc -c
5
(ver capítulo Los comandos filtro - Tratamiento de datos - Recuento de líneas, de palabras y caracteres: wc)
Tercer método
Utilizar el comando expr que muestra el número de caracteres correspondiente a la expresión regular:
$ expr "$palabra" : '.*'
5
(ver capítulo Expresiones regulares - El comando expr)
Cuarto método
Utilizar la función length() del comando awk :
$ echo $palabra | awk '{print length($0)}'
5
(ver capítulo El lenguaje de programación awk - Funciones integradas)
Recuperar el campo de una línea
Objetivo
Recuperar el campo de una línea que posee un separador de campo.
Ejemplo
Recuperar el tercer campo de la variable línea:
$ línea='Newton|Cristina|Londres'
Primer método
Usando el comando cut:
$ echo $línea | cut -d'|' -f3
Londres
El carácter separador | (opción -d) debe ser protegido por apóstrofos para que el shell no lo interprete como un tubo de comunicación.
(Ver capítulo Los comandos filtro - Tratamiento de datos)
Segundo método
Usando el comando awk:
$ echo $línea | awk -F'|' '{print $3}'
Londres
El carácter separador | (opción -F) debe ser protegido por apóstrofos para que el shell no lo interprete como un tubo de comunicación.
(Ver capítulo El lenguaje de programación awk - Variables especiales)
Tercer método
Usando el comando read del shell, modificando la variable IFS.
En ksh:
$ IFS="|"
$ echo "$línea" | read Nombre Apellidos ciudad
$ echo $ciudad
Londres
No hay que olvidar poner comillas entorno a la variable línea ya que contiene el carácter | que es ahora un delimitador (como antes era el espacio). Este carácter no debe ser interpretado por el shell, es necesario que pase por el tubo. El comando read, que es un comando interno, es interpretado por el shell...
No mostrar algunas líneas de un flujo
Objetivo
No mostrar algunas líneas de un archivo o de un flujo de datos.
Ejemplo
No mostrar las líneas del archivo fic.txt que empiezan con un almohadilla.
$ cat fic.txt
# comentario a
instrucción 1
# comentario B
instrucción 2
Primer método
Usando grep y su opción -v:
$ grep -v 'ˆ#' Fic.txt
instrucción 1
instrucción 2
(Ver capítulo Los comandos filtro - Visualización de datos)
Segundo método
Utilizando sed con su opción d (delete):
$ sed '/ˆ#/d' fic.txt
instrucción 1
instrucción 2
(Ver capítulo El comando sed - Uso del comando sed)
Tercer método
Uso de awk y una expresión regular:
$ awk '$0!~ /ˆ#/ { print }' fic.txt
instrucción 1
instrucción 2
(Ver capítulo El lenguaje de programación awk)
Pruebas numéricas
Objetivo
Realizar comprobaciones numéricas en variables que contienen números.
Ejemplo
Comprobar si la variable número es inferior a 100.
Primer método (ksh, bash)
Usar el comando de test [[ ]]:
$ [[ $número -lt 100 ]] && echo '$número < 100'
Observe no utilizar los operadores =, !=, < y > del comando [[ ]] que hacen pruebas lexicográficas (comparación de cadenas) y no numéricas.
(Ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Segundo método
Usar el comando de test [ ]:
$ [$ número -lt 100 ] && echo '$número < 100'
Observe no utilizar los operadores = y != del comando [ ] que hacen pruebas lexicográficas (comparación de cadenas) y no numéricas.
(Ver capítulo Las bases de la programación shell - Ejecución de verificaciones)
Tercer método (ksh, bash)
Usar el comando aritmético (( )):
$ (($ número < 100 )) && echo '$número < 100'
(Ver capítulo Las bases de la programación shell - Aritmética)
Cuarto método
Usar el comando expr:
$ expr $número \< 100 > /dev/null && echo '$número < 100'
El comando expr no es el más cómodo de usar porque hay que proteger los caracteres especiales del shell y eliminar...
Cálculos
Objetivo
Efectuar cálculos aritméticos.
Ejemplo
Multiplicar la variable número por 100.
Primer método (ksh, bash)
Utilizar la sustitución de expresiones aritméticas:
$ numero=$(( $numero * 100 ))
o
$ numero=$(( numero * 100 ))
Segundo método (ksh, bash)
Usar el comando aritmético (( )):
$ (( $número * 100)).
(Ver capítulo Las bases de la programación shell - Aritmética)
Tercer método
Usar el comando expr:
$ expr $número \* 100
El comando expr no es el más cómodo porque hay que proteger a los caracteres especiales del shell y eliminar una visualización innecesaria.
(Ver capítulo Las bases de la programación shell - Aritmética)
En el capítulo Las bases de la programación shell - Aritmética de punto flotante, se presentan ejemplos de cálculos con números de punto flotante.
Ejecutar un script de otro lenguaje a partir de un shell
Objetivo
Ejecutar un script Perl y un script Python a partir de un script shell.
El script Perl
$ nl scriptperl.pl
1 #! /usr/bin/perl
2 print "Soy un script Perl";
3 exit 0;
El script Python
$ nl scriptpython.py
1 #! /usr/bin/python
2 print "Soy un script Python"
3 exit(0)
El script shell
$ nl test_scripts.sh
1 # Ejecución del script Python
2 if scriptpython.py > /dev/null
3 then
4 echo "Script Python termina con éxito"
5 else
6 echo "Script Python termina con error"
7 fi
8 # Ejecución del script Perl
9 if scriptperl.pl > /dev/null
10 then ...
Acceder a una base MySQL a partir de un shell
Objetivo
Ejecutar un comando SQL SELECT a partir de un script y explotar su resultado, luego lanzar la copia de seguridad de una base de datos MySQL.
El script shell
En la línea 3, la consulta SQL recuperará la columna redaccion de la tabla funcion. Los datos se almacenan en la variable lista Funciones. Esta variable se utiliza a continuación en un bucle for en la línea 4.
En la línea 9, el comando mysqldump permite exportar una base de datos al formato SQL.
Si es necesario, se pueden utilizar los códigos de retorno de los comandos mysql y mysqldump (por ejemplo en línea 9).
$ nl test_sql.sh
1 #! /bin/bash
2 # recuperar una lista de funciones a partir de la BD
3 listaFunciones=$(mysql -unomUser -pContrase -h machineServer
--batch --skip-column-names --execute "select redaccion from funcion"
miBaseAGuardar 2>/dev/null)
4 for función in "$listaFunciones"
5 dO
6 echo "Tratamiento de la función $función".
7 done
8 # Respaldar la base de datos
9 if mysqldump -unomUser -pContrase -h machineServer miBaseAGuardar >
/tmp/ miBaseAGuardar.sql...