Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

viernes, 10 de julio de 2015

Trucos y tips útiles en bash scripting

Muchas personas consideran Bash como un lenguaje incompleto que es capaz de realizar muy pocas tareas, aún cuando en realidad no es así. Es cierto que hoy en día existen lenguajes de programación más potentes usados en Linux, tales como Java, Python y Perl, y que estos a veces son incrustados en porciones de código de Bash, pero en más de una ocasión el uso de estos lenguajes es innecesario, pues en realidad Bash es más potente de lo que parece. Es por ello que hoy vengo con unas cuantas curiosidades sobre este lenguaje que más de uno encontrará muy útil.

portada_trucos_bash

Comencemos con el uso de parámetros de entrada. Algunos no tienen constancia de que un script es capaz de recibir argumentos tal y como hacen los lenguajes de alto nivel de hoy en día. Dichos argumentos son referidos con el carácter $ y el número de argumento, siendo $1 el primer parámetro introducido, $2 el segundo y así sucesivamente... Además si se escribiese el parámetro $0 dentro de un script, se estaría haciendo referencia al comando usado para ejecutar el script. Como esto puede resultar un poco lioso, lo plasmaré sobre un ejemplo: En este ejemplo tendremos un script con el siguiente contenido:

  1. #!/bin/bash
  2. echo "Este es el primer argumento recibido: $1"
  3. echo "Este es el segundo argumento recibido: $2"
  4. echo "Este es el nombre del script: $0"

Este script se basa simplemente en una prueba de concepto que imprime los dos primeros argumentos (en caso de haberlos) y el comando usado para ejecutar el script. Dependiendo de lo que introduzcamos a la hora de ejecutar el script, recibiremos resultados distintos, para no poner distintas líneas con diferentes resultados pondré las ejecuciones del script con distintos argumentos y el resultado que mostraría éste; así todo quedará mucho más centralizado:

  1. ./test.sh 1 2
  2. Este es el primer argumento recibido: 1
  3. Este es el segundo argumento recibido: 2
  4. Este es el nombre del script: ./test.sh
  5. ./test.sh hola
  6. Este es el primer argumento recibido: hola
  7. Este es el segundo argumento recibido:
  8. Este es el nombre del script: ./test.sh
  9. /usr/src/test.sh
  10. Este es el primer argumento recibido:
  11. Este es el segundo argumento recibido:
  12. Este es el nombre del script: /usr/src/test.sh

Por otro lado estaría la búsqueda y reemplazo de palabras y frases dentro de una variable (obviamente dicha variable tiene que tener una cadena de texto. Cuando a alguien piensa en este tipo de acciones, enseguida piensa en el uso de arrays y acciones para filtrar ciertas partes de dicho array; acciones que por lo general conllevan un gran número de línea; pero la verdad es que se pueden lograr estos objetivos con una facilidad asombrosa, pues bash ya posee varios métodos específicos para lograr estos objetivos.

Por ejemplo, si quisiésemos mostrar una frase sustituyendo una palabra en concreto por otra, la estructura correcta para realizar dicha acción:

echo ${variable/palabra_a_cambiarr/nueva_palabra}

Hay que tener muy presente que siempre se tratará la cadena como una variable y no que podría realizarse dicha acción sobre una cadena pura. Eso significaría que:

Bien:
  1. #!/bin/bash
  2. cadena="hola esto es una prueba"
  3. echo ${cadena/'prueba'/'falla'}
  4. #hola esto es una falla
Mal:
  1. #!/bin/bash
  2. echo "hola esto es una prueba/prueba/falla"

Otra característica muy típica en los lenguajes de programación más conocidos, es la obtención de la longitud de una variable; dato obtenido generalmente mediante el sufijo .length (depende del tipo de lenguaje). En bash en cambio este dato no se obtiene de esta manera, sino de otra mucho más sencilla: El formato para lograr la longitud de una varíable sería:

${#variable}

Como podéis ver siempre se realiza la acción sobre la variable, nunca sobre el contenido de ésta. Una buena forma de probar esta funcionalidad sería modificando el script anterior para que tras realizar la sustitución calcule la longitud de la cadena y la muestre en pantalla:

  1. #!/bin/bash
  2. cadena="hola esto es una prueba"
  3. cadena=${cadena/'prueba'/'falla'}
  4. echo ${#cadena}
  5. #22


Prosiguiendo con la manipulación y consulta de cadenas, es imposible pasar por alto las famosas subcadenas, también denominadas substrings en muchos lenguajes de programación. Una subcadena, no es ni más ni menos que un trozo de cadena que se ha obtenido desde una posición determinada que puede tener una longitud determinada. Por ejemplo podríamos usar la cadena de antes: Hola esto es una falla y querer únicamente la subcadena esto es. Para lograr dicha subcadena, en bash no existe el parámetro o concepto substring, sino que se usa un término algo más simple que se trata del uso de dos puntos... Para ponernos en un mejor contexto os pondré la estructura de la extracción de una subcadena:

${variable:Posición_inicial}
o
${variable:Posición_inicial:Longitud_subcadena}


Esto significa que o bien se puede obtener una subcadena desde una posición hasta el final de la cadena, o bien se puede especificar la longitud de la subcadena para la cadena extraiga acabe en una posición en concreto. Imaginemos que queremos extraer la subcadena esto es, la y como he mencionado antes... Para ello podríamos modificar el script anterior para que cogiese la variable cadena y extrajese su subcadena desde la posición número 5; subcadena que tendría una longitud de 7 caracteres, ya que si no los especificásemos nos mostraría esto es una prueba. Además también mostraremos la cadena sin especificar su longitud, con el fin de ver como quedaría:

  1. #!/bin/bash
  2. cadena="hola esto es una prueba"
  3. cadena=${cadena/'prueba'/'falla'}
  4. echo ${cadena:5:7}
  5. #esto es
  6. echo ${cadena:5}
  7. #esto es una prueba


También existe la posibilidad de darle un toque más visual a aquello que imprimimos por pantalla; eso se logra mediante la inclusión de Etiquetas de color y mediante el mostrado de la cadena mediante el comando echo -e "cadena". Una etiqueta de color siempre tiene que ser almacenada en una variable y tienen que tener la siguiente estructura:

variable='\e[${codigo_color}m'

Los colores que se quieren especificar poseen un código númerico en concreto; es decir no se puede especificar un color como Rojo, negro, etc... Se tratan de códigos algo complejos de memorizar, es por ello que os listo a continuación cada color con su correspondiente código:

  • Negro             --> 0;30 
  • Gris oscuro   --> 1;30
  • Gris claro      --> 0;37
  • Azul               --> 0;34 
  • Azul claro     --> 1;34
  • Verde            --> 0;32 
  • Verde claro  --> 1;32
  • Cyan             --> 0;36 
  • Cyan claro   --> 1;36
  • Rojo              --> 0;31 
  • Rojo claro     --> 1;31
  • Morado          --> 0;35 
  • Morado claro --> 1;35
  • Marrón           --> 0;33 
  • Amarillo          -->1;33 
  • Blanco            --> 1;37
  • No color         --> 0

Por ejemplo imaginemos que poseemos esta cadena:

Vamos a probar diferentes colores

Queremos mostrar esta cadena con diferentes colores; para ello crearemos cuatro variables llamadas ROJO, CYAN, VERDE y BLANCO y haremos que la palabra vamos se muestre en rojo, las palabras a probar se muestren en cyan, la palabra diferentes se muestre en verde y por último la palabra colores se muestre en blanco.El código para lograr dicho sería el siguiente:

  1. #!/bin/bash
  2. ###COMENZAMOS CREANDO VARIABLES CON COLORES###
  3. ROJO='\e[0;31m'
  4. CYAN='\e[0;36m'
  5. VERDE='\e[0;32m'
  6. BLANCO='\e[1;37m'
  7. #PASAMOS A MOSTRAR EL TEXTO CON COLORES. MUY IMPORTANTE HACER ECHO CON EL PARAMETRO -e
  8. echo -e "${ROJO}Vamos ${CYAN}a probar ${VERDE}diferentes ${BLANCO}colores"

Aunque antes ya he comentado este dato; es muy importante que se incluya el parámetro -e al comando echo, pues en caso contrario no colorearía la cadena. El resultado obtenido sería éste:

texto_color


No podríamos finalizar sin mencionar una gran utilidad usada tanto en shell como en bash, pero que muchos desconocen llamada bc. Dicha utilidad permite tratar los resultados como números reales, haciendo que por ejemplo, a la hora de querer realizar una operación matemática con decimales. nos reconozca las variables como números y nos permita realizar operaciones entre éstas sin problemas. Además, en combinación con bc se puede usar el parámetro scale, pensado para operaciones matemáticas que tengan decimales; scale simplemente tiene como objetivo establecer el número de decimales que tendrá un valor, con el fin de que si por ejemplo tuviésemos un valor con muchos decimales, este acorte dichos decimales redondearía éstos al valor más próximo posible. El uso de estos parámetros tiene la siguiente estructura:

echo "scale=${decimales};${operacion_matemática}" |bc 

Por ejemplo, supongamos que queremos dividir 10 entre 3 y que el resultado muestre únicamente dos decimales. El código para lograrlo sería:

  1. #!/bin/bash
  2. echo "scale=2;10 / 3" |bc
  3. #3,33

Visto esto, obviamente sería un error subestimar la potencia de bash; simplemente es necesario ahondar un poco en este lenguaje para descubrir sus posibilidades.

Saludos.

No hay comentarios :

Publicar un comentario