HERRAMIENTAS ÚTILES

Ya hemos visto que Linux trae embebidos algunos comandos útiles como grep, sort, head o tail. A continuación te mostraré algunas otras herramientas de suma utilidad para el uso cotidiano de Bash.

awk

El nombre awk proviene de las iniciales de sus autores. Es un programa poderosísimo que se utiliza, entre otras cosas, para buscar patrones, procesar texto y extraer información de un archivo. Es sumamente práctico para procesar archivos de tipo csv, o uno cuyo texto esté ordenado en columnas por tabulaciones, o uno cuyas columnas estén separadas por "|", etc.

Comando Descripción
awk -F "," '{print $n}' arch (-Fields) Muestra los datos de la columna n del archivo
awk -F "," '{print $m "sep" $n}' arch Muestra los datos de las columnas m y n del archivo, separadas por sep
awk -F "," -v var=valor '{print var $n}' arch (-variable) Permite imprimir el valor de una variable antes de la columna n
awk -F "," '{op} END {print op}' arch Efectúa una operación e imprime el resultado.
ATENCIÓN: Recordar que la operación va entre llaves ({ }) y que termina con la palabra END
awk -F "," '{suma += $n} END {print suma}' arch Calcula e imprime la suma de todos los valores de la columna n. No olvidar la palabra END
awk -F "," '{prom += $n / m} END {print prom}' arch Calcula e imprime el promedio de la columna n que tiene un total de m valores. No olvidar la palabra END
awk -F "," 'cond {print cond}' arch Evalúa una condición e imprime el resultado
NOTA: Para archivos CSV u otros cuyas columnas estén divididas por otro separador, siempre es necesario especificar la opción -F. Además, el separador puede escribirse entre comillas dobles (") o simples ('), pero la expresión va exclusivamente entre comillas simples.

Archivos CSV

Supongamos que tenemos el archivo alumnos.csv:

Isabel,9 años,8,Matemática
Joaquín,7 años,5,Historia
Kevin,8 años,9,Lengua
Laura,10 años,7,Geografía

Veamos cómo se aplica cada comando:

awk -F "," '{print $1}' alumnos.csv
# Isabel
# Joaquín
# Kevin
# Laura
awk -F "," '{print $1 " => " $2}' alumnos.csv
# Isabel => 9 años
# Joaquín => 7 años
# Kevin => 8 años
# Laura => 10 años
awk -F "," -v mat=" se destaca en " '{print $1 mat $4}' alumnos.csv
# Isabel se destaca en Matemática
# Joaquín se destaca en Historia
# Kevin se destaca en Lengua
# Laura se destaca en Geografía
awk -F "," '{suma += $2} END {print "La suma de todas las edades es " suma}' alumnos.csv
# La suma de todas las edades es 34
awk -F "," '{prom += $3 / 4} END {print "El promedio de calificaciones es " prom}' alumnos.csv
# El promedio de calificaciones es 7.25
awk -F "," '$3 >= 7 {print $1 ": " $3}' alumnos.csv       # Imprimir las calificaciones mayores o iguales a 7
# Isabel: 8
# Kevin: 9
# Laura: 7

Archivo con tabulaciones

Ahora veamos el caso de un archivo de texto con tabulaciones, por ejemplo frutas.txt:

Mariana		manzanas	8
Nicolás		naranjas	13
Octavio		bananas		10
Pablo		duraznos	5
Rogelio		peras		9

Como hay tabulaciones, no es necesario especificar -F:

awk '{print $2}' frutas.txt
# manzanas
# naranjas
# bananas
# duraznos
# peras
awk '{print $2 " = " $3}' frutas.txt
# manzanas = 8
# naranjas = 13
# bananas = 10
# duraznos = 5
# peras = 9
awk -v var=" tiene " '{print $1 var $3 " " $2}' frutas.txt
# Mariana tiene 8 manzanas
# Nicolás tiene 13 naranjas
# Octavio tiene 10 bananas
# Pablo tiene 5 duraznos
# Rogelio tiene 9 peras
awk '{suma += $3} END {print "Hay " suma " frutas en total"}' frutas.txt
# Hay 45 frutas en total
awk '{prom += $3 / 5} END {print "En promedio hay " prom " frutas"}' frutas.txt
# En promedio hay 9 frutas
awk '$3 > 10 {print $1 " tiene más de 10" $1}' frutas.txt
# Nicolás tiene más de 10

Operaciones con decimales

Como se dijo en un capítulo anterior, awk se puede incorporar a nuestros scripts para realizar cálculos con números decimales. Es un procedimiento muy sencillo, usando la palabra BEGIN:

awk 'BEGIN {print 1.95 + 3.76}'       # 5.71

Otra enorme ventaja de awk es que cuenta con ciertas funciones para cálculos más complejos:

Además, si el resultado tiene muchos decimales podemos redondearlo con printf y el operador %.nf, donde n indica la cantidad de dígitos decimales:

awk 'BEGIN {printf "%.3f\n", 1 / 3}'      # 0.333
# \n es opcional y sólo produce un salto de línea

Con la opción -v podemos utilizar variables de nuestro código dentro de las expresiones de awk:

iva=0.21
precio=349.50

awk -v p=$precio -v i=$iva 'BEGIN {print "El total es", p + (p * i)}'       # El total es 422.895

Ejercicios

  1. Crear un archivo de nombre verduras.txt con este código
    albahaca | 14 | $ 10.75
    lechuga	| 2 | $ 6.00
    tomate | 7 | $ 9.50
    zanahoria | 6 | $ 7.25
    cebolla | 8 | $ 5.00
    
    y seleccionar sólo aquellas que tengan igual o más de 6 unidades, imprimiendo su nombre y cantidad.
  2. Calcular y mostrar el costo por 5 unidades de cada verdura.
  3. Calcular y mostrar el precio total si se compraran todas las verduras.

cut

cut es otro programa que se utiliza para dividir el contenido de un archivo. Si bien no es tan poderoso como awk, es más fácil de usar porque su sintaxis es más sencilla:

cut -f col1,col2... -d sep arch

La opción -f (-fields) indica cuáles son las columnas que se quieren mostrar y la opción -d cuál es el separador (por defecto se considera la tabulación, pero puede ser cualquiera).

Veamos cómo funciona empleando nuevamente el archivo alumnos.csv:

cut -f 1,3 -d "," alumnos.csv
# Isabel,8
# Joaquín,5
# Kevin,9
# Laura,7
NOTA: Como se puede apreciar, se imprime también el separador original del archivo, ya sea una coma, una tabulación, etc.

Ejercicios

  1. Con el mismo archivo verduras.txt del ejercicio anterior, mostrar solamente las columnas del nombre y del precio.
  2. Con el archivo frutas.txt anterior, ejecuta la instrucción cut -f 2 frutas.txt. Explica el resultado y corrije el archivo para que se muestren correctamente las columnas de los nombres y las frutas.

cron

En Linux existe el programa cron (Command Run ON) que permite ejecutar tareas preprogramadas automáticamente cada cierto intervalo de tiempo. Estas automatizaciones se agrupan en una tabla llamada crontab, donde se detalla en cada línea una tarea distinta. Cada usuario puede tener su propia crontab o bien puede existir una a nivel global de sistema.

Comando Descripción
crontab -l (-list) Muestra un listado de las tareas programadas
crontab -e (-edit) Abre el editor de texto para poder administrar las tareas [1]
crontab -r (-remove) Elimina la crontab actual

[1] La primera vez que se ejecute Cron pedirá elegir el editor que se usará por defecto. Por supuesto, éste se puede cambiar luego.

La sintaxis es simple: 5 asteriscos separados por espacios (* * * * *) y el nombre del comando o del script a ejecutarse:

* * * * * comando
NOTA: Si lo que se va a ejecutar es un script, se debe escribir su ruta absoluta.

Cada uno de los asteriscos indica una unidad de tiempo. De izquierda a derecha:

  1. Minutos (0 - 59)
  2. Hora (0 - 23)
  3. Día del mes (1 - 31)
  4. Mes (1 - 12)
  5. Día de la semana (0 - 6), donde 0 = domingo

Ejemplos:

45 9 * * 3      # Se ejecuta todos los miércoles a las 9:45
0 19 10 * *     # Se ejecuta todos los 10 de cada mes a las 19:00
30 22 17 11 *   # Se ejecuta cada 17 de noviembre a las 22:30
NOTA: Es recomendable probar primero de modo manual el comando para verificar que funciona adecuadamente.

En Crontab también se utilizan comodines:

Comodín Indica
* Cualquier valor
, Más de un valor
- Rango
*/ Frecuencia

Algunos ejemplos:

* * * * *         # Se ejecutará cada minuto
0 7,13,18 * * *   # Se ejecutará a las 7, a las 13 y a las 18
0 8-12 * * *      # Se ejecutará cada hora entre las 8 y 12 inclusive
*/15 * * * *      # Se ejecutará cada 15 minutos

Ejercicios

  1. Crear un script que guarde el mensaje "¡Hola, mundo!" en un archivo llamado saludo.txt y establecer con Cron que se ejecute cada 5 minutos. (Pista: utilizar el operador >>).
  2. Crear un script que guarde el mensaje "Ya pasó media hora" y se ejecute a la hora y cuarto (15 min) y menos cuarto (45 min), por las pŕoximas 2 horas.
  3. Crear otro que guarde el mensaje "Son las [hora] horas" y que efectivamente se ejecute en punto en las próximas 3 horas. (Pista: utilizar el comando date +%H:%M)

sed

sed (stream editor) es un programa múy útil para modificar el texto de un archivo.

Comando Descripción
sed 's/str1/str2/g' arch Sustituye todas las coincidencias de str1 por str2 (la s indica "sustitución" y la g indica "global"), sin alterar el archivo original
sed -i 's/str1/str2/g' arch (-in-place) Sustituye todas las coincidencias de str1 por str2, modificando el archivo original
sed -n 's/str1/str2/p' arch Sustituye todas las coincidencias de str1 por str2, imprimiendo únicamente aquellas líneas en las que aparece
sed -r 's/regex/str/g' arch (-regular-expression) Permite utilizar expresiones regulares (RegEx)
sed 's/^/pref/' arch Añade un prefijo al comienzo de cada línea

Veamos algunos ejemplos de cómo se aplica sed. Supongamos que tenemos un archivo de texto llamado prueba.txt con el siguiente contenido:

¡Hola, mundo!
Esta es la línea 2
y esta es la línea 3.
¡Bienvenido al mundo de Bash!

Entonces:

sed 's/mundo/universo/g' prueba.txt
# ¡Hola, universo!
# Esta es la línea 2
# y esta es la línea 3.
# ¡Bienvenido al universo de Bash!
sed -i 's/línea/fila/g' prueba.txt    # SÍ se modifica el archivo original
# ¡Hola, mundo!
# Esta es la fila 2
# y esta es la fila 3.
# ¡Bienvenido al mundo de Bash!

cat prueba.txt      
# ¡Hola, mundo!
# Esta es la fila 2
# y esta es la fila 3.
# ¡Bienvenido al mundo de Bash!
sed -n 's/mundo/universo/p' prueba.txt     
# ¡Hola, universo!
# ¡Bienvenido al universo de Bash!
sed -r 's/la línea [2,3]/otra línea/g' prueba.txt      # Sustituye "la línea 2" y "la línea 3" por "otra línea"     
# ¡Hola, mundo!
# Esta es otra línea
# y esta es otra línea.
# ¡Bienvenido al mundo de Bash!
sed 's/^/=> /' prueba.txt     
# => ¡Hola, mundo!
# => Esta es la línea 2
# => y esta es la línea 3.
# => ¡Bienvenido al mundo de Bash!

Ejercicios

  1. Con el mismo ejemplo prueba.txt, sustituir "a es la línea" por "e es el renglón", modificando el archivo original.
  2. Agregar el prefijo "--> " (espacio incluido).
  3. Sustituir todas las "o" por "0" (ceros).
  4. Cambiar todas las "a" y "e" por "4".

tee

El programa tee es muy sencillo: permite guardar el resultado de un comando, al mismo tiempo que lo imprime en pantalla. Cabe remarcar que siempre debe utilizarse en un pipe a la salida de otro comando. Por ejemplo, supongamos que tenemos estos archivos y directorios:

Imágenes
Música
Videos
script1.sh
script2.sh
script3.sh
script4.sh

Y queremos guardar en un archivo de texto un listado con los archivos de scripts únicamente:

ls *.sh | tee scripts.txt

Entonces el siguiente listado se mostrará por consola y se guardará en el archivo scripts.txt:

script1.sh
script2.sh
script3.sh
script4.sh

Ejercicios

  1. Guardar en un archivo de texto todos los nombres de los archivos con extensión jpg.
  2. Guardar en un archivo de texto el historial de comandos utilizados.

tr

tr es un comando que se usa para convertir, reemplazar o borrar caracteres en un archivo. Al igual que tee, debe incluirse como parte de un pipe o bien con el operador < arch (¿recuerdas qué es lo que hace?)

Ejemplos:

echo "¡hola, mundo!" | tr a-z A-Z      # ¡HOLA, MUNDO!

tr a-z A-Z < archivo     # Convierte todo el texto del archivo a mayúsculas

Es importante mencionar que el comando tr NO modifica el archivo original, entonces para guardar el resultado podemos simplemente utilizar el operador >.

tr ... < orig > nuevo
Comando Descripción
tr char1 char2 Reemplaza char1 por char2
tr char1-char2 char3-char4 Reemplaza el rango entre char1 y char2 por el rango entre char3 y char4
tr char1,char2 char3,char4 Reemplaza los caracteres char1 y char2 por char3 y char4 respectivamente
tr [:lower:] [:upper:]
tr a-z A-Z
Convierte las letras minúsculas a mayúsculas. También se puede aplicar al revés
tr [:space:] char Sustituye los espacios por un caracter
tr [:digit:] char Sustituye los dígitos por un caracter
tr -d char (-delete) Borra el o los caracteres indicados
tr -c char1 char2 (-complement) Reemplaza con char2 a todos aquellos caracteres que NO sean char1
tr -s char (-squeeze-repeats) Reduce una secuencia de caracteres repetidos a uno solo (por ejemplo, cuando hay muchos espacios).
tr -s char1 char2 Reduce una secuencia de caracteres repetidos a uno solo, y lo sustituye por char2

Veamos cada uno en detalle:

echo "aprendiendo en bash" | tr [:lower:] [:upper:]      # APRENDIENDO EN BASH
echo "aprendiendo en bash" | tr b-e X      # aprXnXiXnXo Xn Xash
echo "aprendiendo en bash" | tr d,e %      # apr%n%i%n%o %n bash
echo "aprendiendo en bash" | tr [:space:] -      # aprendiendo-en-bash
echo "4pr3nd13nd0 3n b4sh" | tr [:digit:] .      # .pr.nd..nd. .n b.sh
echo "aprendiendo en bash" | tr -d en      # aprdido  bash
echo "aprendiendo en bash" | tr -c en +      # +++en++en+++en++++++
NOTA: El último caracter reemplazado corresponde a \n (salto de línea).
echo "aprendiendo    en    bash" | tr -s ' '      # aprendiendo en bash
echo "aprendiendo    en    bash" | tr -s [:space:] _      # aprendiendo_en_bash

Ejercicios

Vamos a trabajar sobre un archivo llamado deportes.txt con este código:

0- fútbol
1- atletismo
2- ciclismo
3- tenis
4- básquetbol
5- hockey
6- vóleibol
7- natación
8- rugby
9- karate
  1. Reemplazar el guion por ")".
  2. Reemplazar todas las vocales acentuadas por "?". ¿Qué es lo que ocurre y por qué?
  3. Sustituir los números por letras mayúsculas.
  4. Convertir todo el texto a mayúsculas.
  5. Sustituir las "o" por ceros, las "l" por "1" y las "a" por "4", y guardarlo en un archivo nuevo.
  6. Borrar los caracteres "k" e "y".
  7. Sustituir todos los caracteres que NO sean "i" por puntos (".")
  8. Reemplazar el rango n-r por "_".
  9. Quitar todos los caracteres que NO sean dígitos.

uuidgen

uuidgen es un generador de UUIDs. Un UUID (Universal Unique ID) es una cadena de 32 dígitos hexadecimales (dígitos del 0 al 9 y letras de la "a" a la "f"), dividida por guiones en grupos de 8-4-4-4-12 caracteres. Es un identificador único y prácticamente imposible de duplicar, muy utilizado actualmente.

uuidgen     # b299e844-30a9-4533-aecf-88b87b79cc98

Ejercicios

  1. Usando el comando tr, generar un UUID con letras en mayúsculas.
  2. Usando tr nuevamente, sustituir las letras por los números del 0 al 6.
  3. Usar tr para generar un UUID sin guiones.

xargs

El nombre xargs proviene de extended arguments (argumentos extendidos) y es una herramienta que permite aplicar un comando a cada elemento de una lista. También necesita estar dentro de un pipe y combinarse con otros comandos. Es muy provechoso agregarle la opción -t para mostrar cuál es el comando que está ejecutando.

Algunas aplicaciones prácticas de xargs:

Ejercicios

  1. Crear 4 archivos con extensión pdf. (Pista: usar el sufijo {1..4}).
  2. Cambiar su extensión a docx.
  3. Otorgarles permiso de escritura.
  4. Borrar esos archivos.