¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Programación shell en Unix/Linux
  3. Cómo hacer ... (síntesis)
Extrait - Programación shell en Unix/Linux ksh, bash, estándar POSIX (con ejercicios corregidos) (5ª edición)
Extractos del libro
Programación shell en Unix/Linux ksh, bash, estándar POSIX (con ejercicios corregidos) (5ª edición) Volver a la página de compra del libro

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 
> ) 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...