Uso básico del lenguaje bash (Parte 2: Creación de un guión básico en bash)

  En una entrada anterior se ha hablado con cierta profundidad del lenguaje bash. Este tipo de lenguaje se utiliza, generalmente, para crear guiones que facilitan el uso de los sistemas operativos a sus usuarios. Obviamente, en este caso concreto, dichos guiones funcionarán con sistemas operativos de tipo linux, puesto que el lenguaje bash no está diseñado para Windows y sus derivados.
  Como en la mayoría de los lenguajes informáticos, este lenguaje de comandos contiene signos (@, $, #, ...), operadores (+, -, =, ...), valores (cadenas, enteros, booleanos, ...), variables, expresiones, etc., cuyas combinaciones forman las diferentes sintaxis del mismo.
   Todo guión de bash debe iniciarse, como ya se ha dicho en alguna entrada anterior, con el siguiente encabezamiento (situado en la parte superior izquierda del archivo): #!/bin/bash.
  Puede verse que en esta línea se comienza con el signo "#". Este signo nunca se verá fuera de la edición del archivo del guión, pues es para añadir comentarios referentes al contenido del mismo; tales comentarios pueden ser para el programador, para algún futuro usuario del guión, etc. Así pues, cada comentario debe ir línea a línea comenzando siempre por el mencionado signo. Por ejemplo:

#!/bin/bash
#
# Hola Mundo comentado
#
echo "Hola mundo"

VARIABLES

  En este tipo de lenguaje de comandos, las variables no tienen tipo, es decir, una variable puede contener una cadena, un número, etc.,  sin necesidad de definirlo. Además, las variables tendrán ámbito global salvo que estén definidas como local,  lo que significa que se defina la variable donde se defina, se podrá utilizar en cualquier lugar del guión. Sin embargo, si se define dentro de una expresión como local esta sólo tendrá aplicación en la propia expresión.
  Para definir una variable, se emplea la siguiente sintaxis:
<nombre de variable>=<valor de variable>

  Es obligatorio no dejar espacios antes y/o después del signo "=", ya que sino bash interpretaría la variable como un comando linux. Por otra parte, si el valor de esta posee espacios entre sus elementos, debe escribirse entre comillas simples (si se desea que aparezca el contenido exacto), o entre comillas dobles (si se quiere que el contenido sea interpretado).
  Para acceder a una variable simplemente se escribe como prefijo "$" en el nombre de la variable:
  $<nombre de variable>

Un ejemplo sencillo es el siguiente:

#!/bin/bash
# Asignación y salida de variables
variable="Me llamo Rip Van Winkle"
echo $variable


  Cuando se ejecuta desde un terminal o consola se tiene la posibilidad de pasarle más argumentos. Por ejemplo:

./miScript.sh hola 4

  Para recoger estos valores se escribe "$" y, a continuación, el número de posición del argumento pasado. Sin embargo, a partir del décimo argumento que se desee pasar de este modo, la sintaxis es ${<nº de argumento>}.
  El primer argumento tiene valor "$1", que sería ‘hola’, y el segundo argumento sería $2, en el ejemplo sería el número 4. La variable "$0" es el propio nombre del archivo.

#!/bin/bash
#
# Paso de variables
#
echo "El primer argumento es" $1
echo "El segundo argumento es" $2


Además, existen ciertas variables especiales, algunas de las cuales son:
  •   $?: Guarda el valor de salida del último comando ejecutado.
  •   $*: Almacena todos los argumentos. 
  •   $#: Número de argumentos pasados.
  •   $USER: Nombre del usuario que ha ejecutado el guión.
  •   $$: Muestra el identificador del proceso del guión.
  •   $HOSTNAME: Nombre del equipo donde se ejecuta el guión.
  •   $0: Nombre del guión.
  •  $SECONDS: Tiempo transcurrido desde que se inició la ejecución del guión (en segundos).
  •   $LINENO: Indica el número de líneas del guión.
  
  Por otra parte, bash también tiene variables del entorno, las más relevantes son:
  •   $SHELL: Indica el intérprete de comandos que ejecuta el usuario.
  •   $HOME: La ruta del usuario ("/home/<nombre de usuario>").
  •   $USERNAME: Nombre del usuario.
  Una de las utilidades de las variables en la creación guiones es poder guardar el resultado de la ejecución de un comando. Esto puede lograrse si en el valor de la variables se encierra el comando a ejecutar entre comillas inclinadas (`...`), o entre los paréntesis de la operación $(...). Con el mismo método también es posible guardar el resultado de una operación aritmética, mas, en este caso, la operación para el valor donde debe estar la operación aritmética es $((...))

COMPARACIONES

  Los condicionales y bucles se rigen mediante la evaluación de una expresión. Por eso, lo primero es saber cómo programar en bash las evaluaciones de una expresión.
  La evaluación de una expresión da como resultado verdadero o falso. Si la comparación o evaluación de la expresión es verdadera se ejecutará el bucle o la condicional, si es falsa la evaluación no se ejecutará.
  En bash, la sintaxis es la siguiente:
test <expresión>
o
[ <expresión> ]
o
[[ <expresión> ]]

  Un ejemplo de expresión sería [ 3 -eq 5 ], que comprueba si el valor 3 es igual a 5; como es incorrecto, el valor que devuelve es falso. Los símbolos "[" y "]" tienen que estar obligatoriamente separados por un espacio, tanto si son simples como si son dobles. Aunque se continúan empleando los corchetes simples por cuestiones de compatibilidad, los corchetes dobles ofrecen ciertas ventajas sobre los anteriores, entre las que destacan:
  •   No se tienen que utilizar las comillas con las variables, los dobles corchetes trabajan perfectamente con los espacios.
  •   Es posible utilizar los operadores "||" y "&&", así como "<" y ">" para las comparaciones de cadena.
  •   Se puede utilizar el operador "=~" para expresiones regulares.
  •   También se pueden utilizar comodines (*, %, etc.).

Comparaciones numéricas
  •   <Nº1> -eq <nº2>: Devuelve verdadero si "nº1" es igual a "nº2".
  •   <Nº1> -ge <nº2>: Devuelve verdadero si "nº1" es igual o mayor a "nº2".
  •   <Nº1> -gt <nº2>: Devuelve verdadero si "nº1" es mayor a "nº2".
  •   <Nº1> -le <nº2>: Devuelve verdadero si "nº1" es igual o menor a "nº2".
  •   <Nº1> -lt <nº2>: Devuelve verdadero si "nº1" es menor a "nº2".
  •   <Nº1> -ne <nº2>: Devuelve verdadero si "nº1" no es igual a "nº2".

Comparaciones de cadenas
  •   <Cadena1> = <cadena2>: Devuelve verdadero si "cadena1" es idéntica a "cadena2".
  •   <Cadena1> != <cadena2>: Devuelve verdadero si "cadena1" no es idéntica a "cadena2".
  •   <Cadena1>: Devuelve verdadero si "cadena1" es nulo (no significa que su longitud sea cero).
  •   -n <cadena1>: Devuelve verdadero si la longitud de caracteres de "cadena1" es mayor que cero.
  •   -z <cadena1>: Devuelve verdadero si la longitud de caracteres de "cadena1" es cero.

Comparaciones de ficheros
  •   -d <nombre de fichero>: Devuelve verdadero si el fichero es un directorio.
  •   -f <nombre de fichero:> Devuelve verdadero si el fichero es un archivo.
  •   -r <nombre de fichero>: Devuelve verdadero si el fichero puede ser leído.
  •   -w <nombre de fichero>: Devuelve verdadero si el fichero puede ser escrito.
  •   -x <nombre de fichero>: Devuelve verdadero si el fichero es ejecutable.

Comparaciones de expresiones
  •   !<expresión>: devuelve verdadero si "expresión" no se cumple.
  •   <expresión1> -a <expresión2>: devuelve verdadero si "expresión1" y "expresión2" se cumplen (también vale "&&").
  •   <expresión1> -o <expresión2>: Devuelve verdadero si "expresión1" o "expresión2" se cumplen (también vale "||").

CONDICIONALES

  En programación, una sentencia condicional es una instrucción que se pueden ejecutar o no en función del valor de una expresión. En bash, las sentencias condicionales más populares son las siguientes:

If – Then

  Si se traduce esta sentencia
 al lenguaje estándar sería "si se cumple, entonces, realiza la acción", lo que significa que sólo se ejecutará una acción cuando coincida con lo que se determina al principio.
  Su sintaxis es:
if [ <expresión> ]
then
<comandos>
fi


  Es posible anidar sentencias de este tipo creando una sucesión de condicionales en la que al superar una se debe enfrentar a la siguiente.

If – Then – Else
  En este caso, lo que significaría es que 
"si se cumple, entonces, realiza la acción, pero si no es así, realiza otra acción".
  Su sintaxis es:
if [ <expresión> ]
then
<comandos>
else
<comandos>
fi


If – Then – Else if – Else
  El significado de esta sentencia es "si se cumple, entonces, realiza la acción, si no es así, realiza otra acción".
  La sintaxis es:
if [ <expresión1> ]
then
<comandos>
elif [ <expresión2> ]
then
<comandos>
else
<comandos>
fi


  En todos los casos anteriores es posible concatenar expresiones mediante los operadores "&&" (las dos expresiones tienen que ser ciertas) y/o "||" (llega con que una de las expresiones sea cierta).

Case
  Se emplea cuando se desea relizar una comparación con diferentes supuestos.
  Posee la siguiente sintaxis:
case <cadena> in
<cadena1>)
<comandos>
;;
<cadena2>)
<comandos>
;;
*)
<comandos>
;;
esac

  Se comprueba "cadena". Si coincide con "cadena1" se ejecutarán los comandos correspondientes hasta llegar a ";;". Sucede del mismo modo con "cadena2". Si "cadena" no concuerda con "cadena1" o "cadena2", se ejecutará "*". Es posible añadir tantas cadenas de verificación como se desee.

BUCLES

  Un bucle repite los comandos que se han escrito tantas veces hasta que la expresión se verifique. Se suele emplear para automatizar tareas repetitivas. Por otra parte, en un bucle suele ser necesario inicializar la variable "i", especielmente si se emplea el corchete simple; dicha variable sirve, entre otras cosas,  para el uso de contadores en el bucle, que se suele añadir con la forma  "((<contador>))".

For
  Existen muchas maneras de realizar un bucle for en bash. Una muy habitual es la siguiente:
for (( inicializador; condición; incremento ))
do
<comandos>
done


  Mediante este modo de emplear este bucle, la sintaxis es casi idéntica a la de C. Por ejemplo:

#!/bin/bash
for (( c=1; c<=5; c++ ))
do
echo "Bienvenido $c veces..."
done


  Otro modo de emplear un bucle de este tipo es mediante el uso de rangos. El rango se suele expresar con un número de inicio y un número de fin; no obstante, Bash, es lo suficientemente inteligente, como para interpretar que si el número de inicio es mayor que el número de fin, se debe hacer una cuenta regresiva, y también de que si se define un número de paso, se debe contar según este. En este caso la sintaxis sería:
for i in {<nº inicio de rango>..<nº final del rango>..[<nº de definicióndel paso>]}
do
<comandos>
done 

While
  En este caso, el bucle se repetirá mientras se cumpla la condición de la expresión. Su sintaxis es la siguiente:
while [ <expresión> ]
do
<comandos>
[((<contador>))]
done


Until
  Este tipo de bucle se repetirá hasta que se cumpla la condición de la expresión. Posee la sigueinte sintaxis:
until [ <expresión> ]
do
<comandos>
[((<contador>))]
done

  Independientemente de lo que se utilice para crear el bucle, es posible controlar el progreso de su ejecución mediante break (termina el bucle) y continue (salta a la siguiente iteración del bucle). El uso de estos comandos se realiza, generalmente, colocando el que se necesite tras "then" (o después de sus comandos, si los hubiera) en un condicional anidado en el bucle.

EJEMPLOS PRÁCTICOS

  A continuación, se mostrarán algunos ejemplos útiles (de funcionalidad probada) de guiones en bash.

  Lo siguiente puede emplearse como plantilla para poder crear un menú básico:

#!/bin/bash
clear
echo "----------MENU DE OPCIONES----------"
echo ""
PS3='Ingrese su opcion a ejecutar : '
options=("Opcion Nro. 1" "Opcion Nro. 2" "Opcion Nro. 3" "Salir")
select opt in "${options[@]}"
do
    case $opt in
        "Opcion Nro. 1")
            echo "A elegido la opcion 1"
            ;;
        "Opcion Nro. 2")
            echo "A elegido la opcion 2"
            ;;
        "Opcion Nro. 3")
            echo "A elegido la opcion 3"
            ;;
        "Salir")
            break
            ;;
        *) echo invalid option;;
    esac
done

  El siguiente ejemplo se puede usar igual que el anterior, y muestra  cómo crear un menú con submenús:

#!/bin/bash
 
#Muestra el menu general
function _menuPrincipal()
{
    echo "1) menu1"
    echo "2) menu2"
    echo "3) Salir"
    echo
    echo -n "Indica una opcion: "
}
 
function _submenu1()
{
    echo
    echo "1) Submenu1-1"
    echo "2) Submenu1-2"
    echo "3) Salir"
    echo
    echo -n "Indica una opcion: "
}
 
function _submenu2()
{
    echo
    echo "1) Submenu2-1"
    echo "2) Submenu2-2"
    echo "3) Salir"
    echo
    echo -n "Indica una opcion: "
}
 
opc=0
until [ $opc -eq 3 ]
do
    case $opc in
        1)
            opc1=0
            until [ $opc1 -eq 3 ]
            do
                case $opc1 in
                    1)
                        echo "menu 1 submenu 1"
                        ;;
                    2)
                        echo "menu 1 submenu 2"
                        ;;
                    *)
                        _submenu1
                        ;;
                esac
                read opc1
            done
            _menuPrincipal
            ;;
        2)
            opc2=0
            until [ $opc2 -eq 3 ]
            do
                case $opc2 in
                    1)
                        echo "menu 2 submenu 1"
                        ;;
                    2)
                        echo "menu 2 submenu 2"
                        ;;
                    *)
                        _submenu2
                        ;;
                esac
                read opc2
            done
            _menuPrincipal
            ;;
        *)
            _menuPrincipal
            ;;
    esac
    read opc
done

  Este ejemplo muestra cómo hacer una calculadora de terminal:

#! /bin/bash
clear
sum=0
i="y"
echo "Introduce la primera cifra"
read n1
echo "Ahora la segunda"
read n2
while [ $i = "y" ]
do
echo "1.Sumar"
echo "2.Restar"
echo "3.Multiplicar"
echo "4.Dividir"
echo "Introduce el numero de operación seleccionada (1 al 4)"
read ch
case $ch in
    1)sum=`expr $n1 + $n2`
     echo "Resultado de la suma ="$sum;;
        2)sum=`expr $n1 - $n2`
     echo "Resultado de la resta = "$sum;;
    3)sum=`expr $n1 \* $n2`
     echo "Resultado de la multiplicación = "$sum;;
    4)sum=`expr $n1 / $n2`
     echo "Resultado de la división = "$sum;;
    *)echo "Tu selección es incorrecta";;
esac
echo "Quieres continuar (y/n)) ?"
read i
if [ $i != "y" ]
then
    exit
fi
done

  El siguiente ejemplo se utiliza para saber si un servicio se está ejecutando:

#!/bin/bash
echo 'Introduzca el nombre del servicio:'
read SERVICE
if ps ax | grep -v grep | grep $SERVICE > /dev/null
then
echo "El servicio $SERVICE se esta ejecutando"
else
echo "El servicio $SERVICE esta detenido"
fi

  Mediante el siguiente ejemplo es posible descargar paquetes desde la dirección de red que se le indique:

#!/bin/bash
##Llama a wget y descarga lo que se le indique con la velocidad que se le diga
## y en la carpeta que se desee
clear
echo "Puedes ingresar un archivo de texto"
echo "con las direcciones asi: '-i archivo.txt'"
sleep 2
echo -n "Ingresa la direccion a Descargar: "
read descarga
sleep 1
echo "El Destino debe ser una carpeta existente en tu PC"
echo -n "Ingresa la Carpeta de Destino: "
read destino
sleep 1
echo "La Velocidad es en kb o mb Ej: 50k 1m"
echo "o ingresa 0 (cero) para ilimitado"
echo -n "Ingresa la Velocidad de Descarga: "
read velocidad
sleep 1
wget -c --limit-rate=$velocidad -P$destino $descarga
fichero=`basename $descarga`
hora=$(date +%H:%M:%S)
echo "Finalizada la descarga de $fichero en $destino a las $hora"
]sleep 3


  Espero que la presente entrada haya sido interesante para el lector. Si es así, aguardo que el lector la comente y/o la comparta, por favor.

No hay comentarios:

Publicar un comentario

Deje aquí su comentario, si no puede comentar, pruebe a hacerlo desde otro navegador de red u otro equipo.