Este es uno de los capítulos del tutorial El terminal. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
Conforme vas avanzando en los capítulos de este tutorial sobre el terminal, ya estás viendo que esto se está complicando. Sin embargo, que se esté complicando, implica a su vez que le vas a poder sacar mucho mas partido al terminal. Precisamente, este capítulo puede ser el que a priori, le veas menos partido, pero, justo es todo lo contrario. El objetivo de este capítulo es trabajar con archivos de texto, gestionar su contenido, buscar en su interior. Es decir, el objetivo no es mas ni menos que filtrar texto. Para ello, te voy a comentar cuatro herramientas, awk, grep, sed y cut. Estas son algunas de las opciones para filtrar archivos de texto, pero hay muchas mas.
Recuerda que en el capítulo 3 sobre gestionar archivos, te comenté que, en Linux todo es un archivo, con lo que ya estás viendo un poco el potencial de esto. Pero si además, recuerdas que en el capítulo anterior, te comenté la posibilidad de encadenar la ejecución de herramientas, es decir, encadenar la salida de una, a la entrada de otra… el potencial es realmente espectacular.
Y ahora, que ya sabes el potencial que puedes llegar a tener entre tus dedos, ya te estás preguntando, ¿que herramientas necesito?¿como puedo acumular todo ese poder entre mis dedos?.
Filtros: awk, grep, sed y cut
La información está guardada en archivos de texto. Ya sean los archivos de registro o Log, ya sea los archivos de configuración, etc. Pero estos son solo unos pocos, mas si trabajas con archivos de texto plano, como markdown o org-mode. Cualquier cosa que quieras encontrar, es posible encontrarla en segundos, utilizando alguna de las herramientas que vas a ver en este capítulo.
Es mas, hoy en día que no te preocupas por el espacio ocupado, ya que el precio del GB es relativamente muy barato, te has acostumbrado a guardar todo, por si acaso. Tenemos un profundo síndrome de diógenes digital.
Las herramientas que verás en este capítulo para filtrar texto, servirán para paliar este problema.A continuación te mostraré estas herramientas para filtrar texto, y que pronto aprenderás a amar.
Para ver las posibilidades que nos ofrecen estas herramientas he descargado la primera parte de Don Quijote de la Mancha, en texto plano. Tu también la puedes descargar de GitHub, para probar por ti mismo estas herramientas.
awk
awk
busca en archivos en busca de texto que cumpla con un determinado patrón. De esta manera, cuando una línea cumple con ese patrón, awk
realizará una acción en esa línea concreta. Así, entre los parámetros que le vamos a pasar a awk
, también se encuentra, esa acción.
¿Que acciones puedes pasar para que realice awk
? Todas las que puedas imaginar. Y es que awk
es un lenguaje de programación, con lo que ya te puedes hacer una idea de las posibilidades que tienes. Sin embargo, no es el objeto de este tutorial, entrar en detalle, en todas las posibilidades que te da awk, como aplicación o como lenguaje. Simplemente se trata de que veas la punta del iceberg del mismo, y en su caso que te adentres en awk si lo consideras necesario o te puede ser de utilidad para el desempeño de tu trabajo. En este artículo solo vas a ver algunas funciones de awk
, que te permitirán filtrar texto en Linux, de una manera relativamente sencilla.
Uso básico de awk
El uso de awk
es tan sencillo como awk '[intrucciones]' [archivo]
. Dentro de las instrucciones le podemos indicar una condición para que en función de esa condición realice una acción.
Funciones de awk
Dentro de las funciones que permite awk
te indico solo las que considero mas interesante para el filtrado de archivos. Próximamente escribiré un artículo entrando mas a fondo con el uso de esta herramienta y lenguaje, por que ciertamente se lo merece.
length
. Para determinar la longitud de un textoindex
. Indica la posición de una cadena de texto dentro de otra.substr
. Extrae una parte de una cadena.tolower
. Convierte a minúsculas.toupper
. Convierte a mayúsculas.printf
. Imprime el contenido.print
. Igual que el anterior, pero añade un salto de línea.sprintf
. Devuelve una cadena de texto formateada en función de los parámtros indicados.
Como digo estas no son mas que algunas de las funciones que admite awk
.
Parámetros de awk
Por otro lado, puedes utilizar algunos parámetros que te facilitarán enormemente el trabajo con awk
. Algunos de estos parámetros son los siguientes,
$0
. Se corresponde con una línea completa.$1, $2, $3,....
. Se corresponden con la primera palabra, con la segunda palabra, etc.FS
. Es el separador.NF
. Es el número de palabras de una línea.
Algunos ejemplos y usos de awk
Si en nuestro ejemplo quieres imprimir todas las líneas, utiliza
awk '{print}' el_quijote.txt
o bien
awk '{print $0}' el_quijote.txt
¿Y si quisieras imprimir solo las que contienen la palabra Sancho
? En ese caso, tendrías que ejecutar
awk '/Panza/ {print $0}' el_quijote.txt
Lo que ves entre //
es una expresión regular, que ya te he comentado en el capítulo 5 sobre comodines y expresiones regulares. Si quieres imprimir solo aquellas que empiezan con la palabra Sancho
, utilizarás como ya sabes,
awk '/^Sancho/ {print $0}' el_quijote.txt
Para que las búsquedas no tengan en cuenta mayúsculas y minúsculas, la cosa se complica ligeramente.
awk 'BEGIN{IGNORECASE=1} /^sancho/ {print $0}' el_quijote.txt
extraer palabras con print
Una características muy interesante de print
es que nos permite extraer palabras de cada línea. Por ejemplo si quieres imprimir la primera palabra de cada línea, donde aparezca Quijote
, tendrías que ejecutar,
awk '/Quijote/ {print $1}' el_quijote.txt
Un ejemplo práctico. Si listamos ls -lah
en el directorio donde hemos creado los archivos indicados, nos devolverá algo similar a,
-rw-rw-r-- 1 lorenzo lorenzo 12 mar 15 07:47 ejemplo1.txt
-rw-rw-r-- 1 lorenzo lorenzo 12 mar 15 07:47 ejemplo2.txt
-rw-rw-r-- 1 lorenzo lorenzo 1,1M ene 26 2017 el_quijote.txt
¿Como imprimir el nombre del archivo seguido del tamaño?
ls -lah | awk '{print $5 "-" $9}'
Esto es así porque considera como delimitador el espacio. Ahora bien, puedes cambiar el delimitador para que en lugar de ser un espacio sea ;
. Y aquí es donde ya ves el potencial a la hora de trabajar con hojas de cálculo en formato CSV.
El primer paso es cambiar el delimitador. Para ello, pasaremos como parámetro -F
, que nos permite indicar el delimitador. El segundo paso es crear un par de archivos, para poder prácticar con esta nueva opción. Para esto, vamos a ejecutar estas dos órdenes,
echo "1 2 3 4 5 6" > ejemplo1.txt
echo "1;2;3;4;5;6" > ejemplo2.txt
Si quisieras extraer la tercera columna de los archivos que has creado anteriormente, solo tienes que ejecutar,
awk '{print $3}' ejemplo1.txt
awk '{print $3}' ejemplo2.txt
En el caso de ejemplo1.txt
te devolverá 3
. Sin embargo, en el caso del segundo archivo te devolverá 1;2;3;4;5;6
. Sin embargo, si cambiamos el delimitador con la opción -F ';'
el resultado será el esperado.
awk -F ';' '{print $3}' ejemplo2.txt
grep
Esta herramienta te permitirá imprimir todas aquellas líneas que coincidan con el patrón que hayas especificado. Pero no solo, esto, sino que puedes buscar todas las líneas de todos los archivos. ¿Ves las posibilidades?.
Imáginate mi caso, donde todos los artículos que puedes leer en este blog, los he escrito en Markdown. ¿Sabes lo que me cuesta buscar en que artículo escribí sobre Touchpad-Indicator? Tan sencillo como ejecutar el siguiente comando,
grep -i -r 'touchpad-indicator' /home/lorenzo/articulos/*
Las opciones que he añadido son,
-i
para que no distinga entre mayúsculas y minúsculas-r
esta opción es para realizar una búsqueda recursiva
También es posible combinar las opciones de forma que quedará como grep -ir
.
Pero no solo esto, sino que también podemos contar las veces que aparece una palabra dentro de un archivo. Así, si queremos ver las veces que aparece quijote
dentro de nuestro texto, ejecutaremos,
grep -ic 'quijote' el_quijote.txt
Lo que da un total de 590 veces. Si además, quieres ver las líneas donde no aparece, ejecuta,
grep -icv 'quijote' el_quijote.txt
Lo que da un resultado de 1596
veces. La opción -v
te permite, buscar todas aquellas líneas donde no se encuentre el patrón indicado.
Si quieres buscar todos los archivos donde está la palabra quijote, y que además las cuente, utiliza,
grep -isrc 'quijote' *
El problema de esta ejecución es que te devuelve todos los archivos, junto con el número de repeticiones. Evidentemente, la mayoría aparecerán como 0
. ¿Como quitar esas líneas que no nos dan ninguna información? Encadenando dos ejecuciones de grep
, tal y como puedes ver a continuación,
grep -isrc 'quijote' * | grep -v ':0$'
Esto te dará el siguiente resultado,
el_quijote.txt:590
sed
Esta es una de las herramientas que junto con las anteriores, mas potencial tiene a la hora de realizar el filtrado y transformación de archivos de texto. En definitiva, sed
es un editor de flujo de texto. Este editor de flujo te permite realizar transformaciones en el flujo de entrada.
Dentro de todas las posibilidades que te ofrece lo mas utilizado es la posibilidad de sustituir texto. Para ello, de nuevo hace uso de las expresiones regulares. Es importante que tengas en cuenta, que lo que hace es modificar el flujo de entrada, pero no el archivo original, es decir, te ofrece un flujo de salida modificado. Si quieres guardar ese flujo de salida modificado deberás hacer uso de los operadores de redirección.
El uso de esta herramienta es el siguiente
sed 'operación' archivo
Algunos ejemplos del uso de sed
Si quieres reemplazar todas las apariciones de panza
por barriga
en el archivo de ejemplo, utiliza la siguiente orden,
sed 's/panza/barriga/g' el_quijote.txt
Si quieres que esto se haga con independencia de mayúsculas y minúsculas,
sed 's/Panza/Barriga/gi' el_quijote.txt
Así el resultado que obtendrás será algo como,
Sancho Barriga es aquéste, en cuerpo chico
pero grande en valor, ¡milagro extraño!
Escudero el más simple y sin engaño
que tuvo el mundo, os juro y certifico.
Si quieres guardar esta alternativa, utilizando los operadores de redirección,
sed 's/Panza/Barriga/gi' el_quijote.txt > el_quijote_v2.txt
Si quieres reemplazar dos o mas espacios por uno solo,
sed 's/\s+/ /g' el_quijote.txt
En el caso de que quisieras insertar un asterisco al principio de cada línea,
sed 's/^/*/g' el_quijote.txt
cut
Esta herramienta te permite mostrar por la salida estándar, es decir, por pantalla, parte de cada una de las líneas del archivo que le pases. Es decir, le puedes indicar, de cada línea o fila del archivo que es lo que quieres que te muestre. Al igual que otras herramientas, esta también dispone de una serie de opiones que te permite definir que es lo que quieres mostra de cada una de las líneas.
-b
permite seleccionar un byte o listado de bytes separados por comas. También es posible definir rangos. Para definir rangos tienes que utilizar-
. Así para definir del byte 1 al 10, tienes que indicar-b 1-10
. Si lo que quieres es del byte 1 al final,-b 1-
. Por contra, si lo que quieres es seleccionar hasta el byte 5, utiliza-b -5
.-c
lo mismo que en el caso anterior pero esta vez para caracteres.-d
por defectocut
tiene definido como delimitador el tabulador. Con esta opción, puedes definir otro delimitador distinto.f
esta opción te permite seleccionar los campos. Un campo es el elemento situado entre delimitador y delimitador. Si seleccionas mas de un campo, te los devolverá separados con el delimitador que hayas indicado.
Un uso muy interesante de cut
es como archivos CSV, me refiero a los archivos separador por comas. Realmente, yo los prefiero utilizar separados por punto y coma, por aquello de los decimales. Así, suponiendo que me haces caso, y los separas por punto y coma, partiendo de este archivo letras.csv
, prueba con algunas opciones.
a;b;c;d;e;f;g;h
cut -d ';' -f 3 letras.csv
->c
cut -d ';' -f 3,5,7 letras.csv
->c;e;g
cut -d ';' -f 3- letras.csv
->c;d;e;f;g;h
cut -d ';' -f -5 letras.csv
->a;b;c;d;e
Conclusiones
Indicar que cada una de las herramientas que has visto en este capítulo del tutorial, ya se merece un capítulo por si misma. Solo tengo que recordarte que awk es un lenguaje de programación, o sea que imagínate todo lo que se puede hacer. Aquí solo has visto la punta del iceberg.
Sin embargo, este es el uso mas frecuente que yo le doy a estas herramientas, con lo que te puede servir de orientación.
Por último, indicarte que este capítulo de filtros lo he tenido que dividir en dos partes, por la cantidad de herramientas que hay disponibles. En la siguiente parte del tutorial, tendrás a tu disposición un nuevo abanico de herramientas disponibles.
Más información,
El contenido es extremadamente útil y conciso.
Muchas gracias por tu esfuerzo y dedicación.
Muchísimas gracias a ti Mario
Tengo una duda llevo una semana intentando filtrar una tabla csv para que solo muestre las lineas que en su columna 9 tenga como valor 3 (sin decimal), la guía es una maravilla didáctica, Gracias
Tengo una duda llevo una semana intentando filtrar una tabla csv para que solo muestre las lineas que en su columna 9 tenga como valor 3 (sin decimal), la guía es una maravilla didáctica, Gracias
sudo cut -d «,» -f 1,2,8,9 1480.csv | ./cmd.sh Perdon este es la línea
¿Cómo quitaría solo el último elemento de la lista con cut, independientemente de la cantidad de elementos?