🚨 ¡Nueva review! ¡Mi teclado ideal! ⌨️ Perfecto para programar, el Logitech MX Keys S . ¡Échale un ojo! 👀

Comando AWK en Linux: guía completa con ejemplos prácticos

Domina AWK para manipular texto, filtrar datos y transformar ficheros desde la terminal

Escrito por domin el 24 de marzo de 2025 · Actualizado el 8 de febrero de 2026

🧙‍♂️🦄 AWK: una herramienta muy potente para manipular texto en Linux

Utilizando Linux en el mundo profesional, y también en el personal, más de una vez nos vamos a encontrar en la situación de tener que manipular texto y transformar datos. AWK es una gran herramienta para ello.

AWK es una herramienta de línea de comandos en Linux y también es un lenguaje de programación diseñado para procesar textos y datos. No es un simple comando, es prácticamente un lenguaje completo con variables, funciones, condicionales y bucles. Todo metido en un solo comando de terminal.

El nombre AWK viene de las iniciales de sus creadores: Aho, Weinberger y Kernighan, todos estadounidenses. Fue creado en 1977 en los laboratorios Bell de AT&T (el mismo sitio donde nacieron Unix y C), así que lleva casi 50 años haciendo su trabajo y sigue siendo una de las herramientas más usadas en cualquier servidor Linux.


¿Cómo funciona?

AWK trabaja línea por línea. Lee un fichero (o la entrada estándar), divide cada línea en campos y te permite trabajar con ellos. Por defecto, separa los campos por espacios o tabulaciones.

Piensa en ello como una hoja de cálculo en la terminal: cada línea es una fila y cada palabra separada por espacios es una columna. Tú le dices “quiero la columna 2 de las filas que cumplan X condición” y AWK te lo saca al instante.

$0

La línea completa

$1

Primera columna

$2

Segunda columna

$NF

Última columna


Sintaxis básica

La estructura general para usar AWK es:

awk 'condición { acción }' fichero.txt

Si no pones condición, la acción se aplica a todas las líneas. Si no pones acción, por defecto imprime la línea completa.


Variables especiales de AWK

AWK tiene unas cuantas variables internas que conviene conocer:

NR

Número de línea actual (Number of Records). Se incrementa con cada línea leída.

NF

Número de campos de la línea actual (Number of Fields). $NF es la última columna.

FS

Field Separator. El delimitador de campos. Por defecto es el espacio.

OFS

Output Field Separator. El separador para la salida. Por defecto es el espacio.

RS

Record Separator. El separador de registros (líneas). Por defecto es el salto de línea.

FILENAME

El nombre del fichero que se está procesando.


Ejemplos prácticos

Imagina que tenemos el siguiente fichero ejemplo_awk.txt:

PACO 25 Panadero
PEPE 30 Fontanero
JUAN 35 Mecánico
CARLOS 67 Jubilado

Extraer columnas

Queremos obtener únicamente los nombres de las personas del fichero:

awk '{print $1}' ejemplo_awk.txt

🧙 Salida: bash PACO PEPE JUAN CARLOS


¿Queremos extraer la profesión? Solo tendríamos que cambiar la columna a $3:

awk '{print $3}' ejemplo_awk.txt

🧙 Salida: text Panadero Fontanero Mecánico Jubilado


¿Y si queremos nombre y profesión juntos?

awk '{print $1, $3}' ejemplo_awk.txt

🧙 Salida: bash PACO Panadero PEPE Fontanero JUAN Mecánico CARLOS Jubilado


🧙‍♂️ ¿Fantástico verdad?

Filtrar con condiciones

Queremos extraer únicamente los que estén laboralmente activos, es decir, filtrar por edad y que aparezcan los nombres y las profesiones pero no la edad:

awk '$2 < 65 {print $1, $3}' ejemplo_awk.txt

🧙 Salida: bash PACO Panadero PEPE Fontanero JUAN Mecánico


Más ejemplos de condiciones:

# Solo líneas donde la profesión sea "Fontanero"
awk '$3 == "Fontanero"' ejemplo_awk.txt

# Líneas donde la edad esté entre 25 y 40
awk '$2 >= 25 && $2 <= 40' ejemplo_awk.txt

# Líneas que contengan la letra "A" en el nombre
awk '$1 ~ /A/' ejemplo_awk.txt

Formatear texto

Los nombres están en mayúsculas y no mola mucho, así que vamos a formatearlos. AWK tiene funciones de texto integradas:

awk '{print toupper(substr($1,1,1)) tolower(substr($1,2))}' ejemplo_awk.txt

🧙 Salida: bash Paco Pepe Juan Carlos


Otras funciones de texto útiles:

# Convertir todo a minúsculas
awk '{print tolower($0)}' ejemplo_awk.txt

# Convertir todo a mayúsculas
awk '{print toupper($0)}' ejemplo_awk.txt

# Longitud del nombre
awk '{print $1, length($1)}' ejemplo_awk.txt

# Reemplazar texto
awk '{gsub("Jubilado", "Retirado"); print}' ejemplo_awk.txt

Hacer cálculos

También podemos sacar cálculos de estos datos, como por ejemplo la media de edad de las personas del fichero:

awk '{sum += $2} END {print "Media de edad:", sum/NR}' ejemplo_awk.txt

🧙 Salida: bash Media de edad: 39.25


Más cálculos:

# Suma total de edades
awk '{sum += $2} END {print "Suma total:", sum}' ejemplo_awk.txt

# Edad máxima
awk 'BEGIN {max=0} $2 > max {max=$2; nombre=$1} END {print nombre, max}' ejemplo_awk.txt

# Contar cuántos registros cumplen una condición
awk '$2 < 65 {count++} END {print "Activos:", count}' ejemplo_awk.txt

Los bloques BEGIN y END

AWK tiene dos bloques especiales que son muy útiles:

BEGIN

Se ejecuta antes de procesar la primera línea. Ideal para inicializar variables, imprimir cabeceras o configurar separadores.

END

Se ejecuta después de procesar la última línea. Perfecto para imprimir totales, medias o resúmenes.

awk '
  BEGIN {print "=== INFORME DE PERSONAL ==="; print ""}
  $2 < 65 {print $1, "-", $3; count++}
  END {print ""; print "Total activos:", count}
' ejemplo_awk.txt

🧙 Salida: ```bash === INFORME DE PERSONAL ===

PACO - Panadero PEPE - Fontanero JUAN - Mecánico

Total activos: 3


---

## Cambiar el separador de campos

Por defecto AWK separa por espacios, pero puedes cambiarlo con `-F`. Esto es brutal para trabajar con CSVs, ficheros de configuración y logs:

```bash
# Procesar un CSV (separado por comas)
awk -F',' '{print $1, $3}' datos.csv

# Procesar /etc/passwd (separado por :)
awk -F':' '{print $1, $7}' /etc/passwd

# Separador de múltiples caracteres
awk -F'::' '{print $1}' fichero.txt

# Cambiar también el separador de salida
awk -F',' 'BEGIN{OFS=" | "} {print $1, $2, $3}' datos.csv

El ejemplo de /etc/passwd es muy típico. Cada línea tiene el formato usuario:x:uid:gid:info:home:shell, separado por :. Con AWK puedes extraer cualquier campo al instante:

# Listar todos los usuarios y su shell
awk -F':' '{print $1, "->", $7}' /etc/passwd

# Solo usuarios con shell bash
awk -F':' '$7 == "/bin/bash" {print $1}' /etc/passwd

# Usuarios con UID mayor que 1000 (usuarios normales)
awk -F':' '$3 > 1000 {print $1, $3}' /etc/passwd

AWK con pipes

AWK se vuelve todavía más potente cuando lo combinas con otros comandos usando pipes (|):

# Espacio en disco por partición (solo las que superan el 50%)
df -h | awk '$5+0 > 50 {print $6, $5}'

# Procesos que consumen más de 1% de CPU
ps aux | awk '$3 > 1.0 {print $11, $3"%"}'

# IPs con más conexiones al servidor
netstat -an | awk '/ESTABLISHED/ {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

# Top 5 comandos más usados en tu historial
history | awk '{print $2}' | sort | uniq -c | sort -rn | head -5

# Tamaño total de archivos .log
find /var/log -name "*.log" -exec ls -l {} \; | awk '{sum += $5} END {print "Total:", sum/1024/1024, "MB"}'

Procesando logs: donde AWK realmente brilla

Si hay un sitio donde AWK se gana el pan, es procesando ficheros de log. Imagina un log de accesos de Apache/Nginx con el formato típico:

192.168.1.10 - - [15/Mar/2025:10:15:30] "GET /index.html HTTP/1.1" 200 1234
192.168.1.20 - - [15/Mar/2025:10:15:31] "POST /api/login HTTP/1.1" 401 567
192.168.1.10 - - [15/Mar/2025:10:15:32] "GET /css/style.css HTTP/1.1" 200 890
192.168.1.30 - - [15/Mar/2025:10:15:33] "GET /admin HTTP/1.1" 403 234
10.0.0.1 - - [15/Mar/2025:10:15:34] "GET /index.html HTTP/1.1" 200 1234

Con AWK puedes sacar información muy útil de estos logs:

# Contar peticiones por IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn

# Solo errores (códigos 4xx y 5xx)
awk '$9 >= 400 {print $1, $9, $7}' access.log

# Peticiones al endpoint /api/login que fallaron
awk '$7 ~ /\/api\/login/ && $9 != 200 {print $1, $9}' access.log

# Total de bytes transferidos
awk '{sum += $10} END {print "Total:", sum/1024/1024, "MB"}' access.log

# Peticiones por hora
awk '{split($4, a, ":"); print a[2]":00"}' access.log | sort | uniq -c

# IPs que han recibido un 403 (posibles intentos de acceso no autorizado)
awk '$9 == 403 {print $1, $7}' access.log

Condicionales y bucles

AWK es un lenguaje completo, así que tiene if/else, for, while… la herramienta de la terminal convertida en un mini lenguaje de programación:

# Clasificar personas por edad
awk '{
    if ($2 < 30) categoria = "Joven"
    else if ($2 < 65) categoria = "Adulto"
    else categoria = "Jubilado"
    print $1, "-", categoria
}' ejemplo_awk.txt

# Imprimir cada campo de una línea en líneas separadas
awk '{for (i=1; i<=NF; i++) print "Campo " i ": " $i}' ejemplo_awk.txt

🧙 Salida del primero: bash PACO - Joven PEPE - Adulto JUAN - Adulto CARLOS - Jubilado


Arrays asociativos

Una de las funcionalidades más potentes de AWK son los arrays asociativos (como los diccionarios de Python o los maps de otros lenguajes):

# Contar ocurrencias de cada profesión
awk '{profesiones[$3]++} END {for (p in profesiones) print p, profesiones[p]}' ejemplo_awk.txt

# Suma de edades por profesión (útil con datos más grandes)
awk '{suma[$3] += $2; count[$3]++} END {
    for (p in suma) print p, "- Media:", suma[p]/count[p]
}' ejemplo_awk.txt

Esto es especialmente útil con logs grandes. Imagina contar cuántas peticiones ha hecho cada IP en un log de millones de líneas: AWK lo hace en segundos.


Funciones integradas más útiles

FunciónDescripciónEjemplo
length(s)Longitud de un stringlength($1)
substr(s,i,n)Subcadena desde posición i, n caracteressubstr($1,1,3)
toupper(s)Convertir a mayúsculastoupper($1)
tolower(s)Convertir a minúsculastolower($1)
gsub(r,s,t)Reemplazar todas las ocurrencias de r por s en tgsub("a","e",$1)
sub(r,s,t)Reemplazar solo la primera ocurrenciasub("a","e",$1)
split(s,a,d)Dividir string s en array a usando delimitador dsplit($4,arr,":")
sprintf(f,...)Formatear string (como printf de C)sprintf("%05d",$2)
index(s,t)Posición de t dentro de s (0 si no está)index($0,"error")

Formatear la salida con printf

Si quieres un control más preciso sobre el formato de salida, usa printf en lugar de print:

# Salida formateada con columnas alineadas
awk '{printf "%-10s %3d  %s\n", $1, $2, $3}' ejemplo_awk.txt

🧙 Salida: bash PACO 25 Panadero PEPE 30 Fontanero JUAN 35 Mecánico CARLOS 67 Jubilado


Los formatos más comunes de printf:


One-liners útiles para el día a día

Estos son comandos de una línea que uso frecuentemente y que te pueden sacar de un apuro:

# Eliminar líneas en blanco de un fichero
awk 'NF > 0' fichero.txt

# Eliminar líneas duplicadas (manteniendo el orden)
awk '!seen[$0]++' fichero.txt

# Imprimir solo líneas entre la 5 y la 10
awk 'NR >= 5 && NR <= 10' fichero.txt

# Imprimir la última columna de cada línea
awk '{print $NF}' fichero.txt

# Invertir el orden de las columnas
awk '{for (i=NF; i>0; i--) printf "%s ", $i; print ""}' fichero.txt

# Sumar una columna numérica de un CSV
awk -F',' '{sum += $3} END {print sum}' datos.csv

# Numerar las líneas de un fichero
awk '{print NR, $0}' fichero.txt

# Imprimir líneas más largas de 80 caracteres
awk 'length > 80' fichero.txt

Conclusión

AWK es una de esas herramientas que cuanto más la usas, más te das cuenta de lo brutalmente potente que es. Con una sola línea puedes hacer cosas que en otros lenguajes te llevarían 20 líneas de código.

Las claves para dominar AWK:

Y recuerda: man awk siempre está ahí para cuando necesites profundizar.

EA, ¡nos leemos! 🍻


Pon a prueba lo aprendido

1. ¿De dónde viene el nombre AWK?

2. ¿Qué hace $0 en AWK?

3. ¿Qué representa la variable NR en AWK?

4. ¿Cómo cambias el separador de campos para procesar un CSV?

5. ¿Cuándo se ejecuta el bloque BEGIN?

6. ¿Qué hace el comando: awk '{sum += $2} END {print sum/NR}' fichero.txt?

7. ¿Qué diferencia hay entre gsub() y sub() en AWK?

8. ¿Qué hace el comando: awk '!seen[$0]++' fichero.txt?