Nov 222013
 

En ocasiones como parte de nuestro trabajo de administración de sistemas, puede que sea conveniente escribir un shell script interactivo, que solicite algún dato al usuario. Pero si el usuario no responde al cabo de cierto tiempo, queremos que el script continúe su ejecución asumiento un valor por defecto para la respuesta.

En este artículo se exploran las posibilidades que existen a la hora de implementar una funcionalidad de este tipo en un script bash

1. Solicitar un dato al usuario y leer la respuesta

El comando read se encarga de leer una línea introducida por el usuario y asignársela a una variable. Casi siempre se utiliza con el modificador “-p” (prompt), para presentar en pantalla un texto en el que se solicita el dato. Por ejemplo. con un script de la forma:

#!/bin/bash
read -p "Nombre del fichero: " nombre_fichero
echo "El fichero a procesar es: $nombre_fichero"

obtenemos la siguiente salida:

$ ./lectura_de_teclado.sh
Nombre del fichero: datos.txt
El fichero a procesar es: datos.txt

2. Leer más de una variable con un mismo comando read

El comando read admite especificar más de una variable a ser leída. En este caso, el script divide la información introducida por el usuario utilizando como separador el carácter IFS (que por defecto es un espacio en blanco).

Ejemplo:

El siguiente script:

#!/usr/bin/bash
read -p "Introduzca varios números: " num1 num2 
echo "El primer número es $num1"
echo "El segundo número es $num2"

Genera la siguiente salida:

$ ./lectura_de_teclado.sh 
Introduzca varios números: uno dos
El primer número es uno
El segundo número es dos

$ ./lectura_de_teclado.sh 
Introduzca varios números: uno dos tres cuatro
El primer número es uno
El segundo número es dos tres cuatro

Como vemos, en el segundo caso se han introducido más datos de los que espera el script, y el resultado es que a la última variable especificada ($num2) se le asignan todos los datos restantes.

3. Lectura con timeout

Para quedar a la espera de que el usuario introduzca el dato que se le solicita durante un tiempo limitado, el comando read dispone del modificador “-t”, que permite especificar el número máximo de segundos antes de que el script continue su ejecución.

Si se alcanza el tiempo límite, el valor de las variables a leer queda en blanco, y el comando read devuelve un código de status distinto de cero:

 

#!/bin/bash
if read -t 60 -p "Nombre del fichero: " nombre_fichero; then
    echo "El nombre del fichero es: $nombre_fichero"
else
    echo "Se ha alcanzado el límite de tiempo. Código de salida: $?"
fi

4. Lectura de contraseñas

Si el script necesita solicitar una contraseña al usuario, es interesante hacerlo de tal modo que lo que teclea el usuario no se presente en pantalla. El modificador “-s” del comando read implementa esta funcionalidad:

#!/bin/bash
read -s -p "Clave de acceso : " mi_clave
echo
echo "La clave que has introducido es: - $mi_clave"

 5. Lectura del teclado carácter a carácter

Por defecto, el comando “read” espera a que el usuario introduzca una línea completa, finalizando con la tecla “Intro”

Pero en ocasiones, nos puede interesar que el comando lea cualquier tecla que haya sido pulsada, sin esperar a que finalice la línea.

Esto se consigue utilizando el modificador “-n”, para especificar el número de caracteres que se desea leer. En particular, con “-n 1” indicamos al comando “read” que finalize en cuanto el usuario haya pulsado una tecla:

#!/bin/bash
read -n 1 -p "Pulsa una tecla : " mi_caracter
echo
echo "La tecla pulsada es: - $mi_caracter"

6. Uso del IFS

El IFS (Input Field Separator) es una variable global cuyo valor es el carácter o caracteres que funcionan como delimitador para separar un valor de otro en la línea leída.

Podemos imprimir el valor del IFS con el siguiente comando:

$ cat -et <<<"$IFS"
 ^I$
$

Como podemos ver, el IFS por defecto es cualquiera de:

  • un espacio en blanco
  • un tabulador
  • un salto de línea

Pero en ocasiones, podemos tener como valor de una variable una secuencia de valores unidos por otro tipo de separador (una coma, dos puntos, etc…)

Cambiando temporalmente el valor del IFS, podemos utilizar el comando “read” para descomponer este valor en los valores individuales de que consta.

Por ejemplo, supongamos que tenemos que procesar una línea en el formato del fichero /etc/passwd

linea="miusuario:x:1002:1002::/home/miusuario:/bin/sh"

Comenzamos por guardar el valor de la variable IFS, para poder recuperarlo más tarde, y asignar temporalmente el carácter “:” como separador

IFS_anterior="$IFS"
IFS=:

Con esto, podemos descomponer el valor de la línea en los campos de que consta, con el comando “read”:

read usuario clave uid gid info home shell <<< "$linea"

Y por último, volvemos a asignar a IFS el valor que tenía previamente:

IFS=”$IFS_anterior”

 Publicado por en 8:50 am

 Deja un comentario

(requerido)

(requerido)