- awk es una herramienta y lenguaje de scripting orientado al procesamiento de texto por líneas y columnas, ideal para filtrar, transformar y analizar salidas de comandos y archivos.
- Permite definir patrones y acciones combinando expresiones regulares, variables especiales como $0, $1, NF o NR, y funciones como length, substr o match para hacer filtros muy precisos.
- awk trabaja cómodamente con delimitadores y campos usando FS, OFS y opciones como -F, y puede formatear salidas con print y printf, hacer operaciones matemáticas y gestionar variables con -v.
- Es posible crear scripts awk completos que automatizan tareas complejas, incluyendo búsquedas y sustituciones con gsub, cálculos avanzados y generación de informes a partir de comandos como ps, df o ficheros del sistema.

Cuando empiezas a tomarte en serio la consola de Linux descubres que trabajar con texto no es solo mirar ficheros con cat y poco más. En cuanto te metes en logs enormes, listas de procesos, salidas de comandos o ficheros CSV, necesitas algo mucho más potente para filtrar, transformar y resumir datos sin volverte loco.
Ahí es donde entra en juego awk: un comando que, más que un simple filtro, es prácticamente un lenguaje de programación orientado al procesamiento de texto. Te permite buscar patrones, elegir columnas, hacer cálculos, definir condiciones, usar variables, bucles, funciones… y hasta escribir scripts completos. En este tutorial de awk en Linux vamos a verlo con calma, desde lo básico hasta usos bastante avanzados, integrando todo tipo de ejemplos reales de consola.
¿Qué es awk y para qué sirve en Linux?
Awk es una herramienta de línea de comandos y a la vez un lenguaje de scripting pensada para analizar texto estructurado en líneas y campos. Su nombre viene de las iniciales de sus creadores (Aho, Weinberger y Kernighan) y lleva funcionando desde finales de los años 70, pero sigue siendo una pieza clave en cualquier entorno Unix o GNU/Linux (por ejemplo para ejecutar Unix antiguo en tu PC).
La filosofía de awk es muy sencilla: recorre un archivo (o la salida de un comando) línea por línea, divide cada línea en columnas según un separador, comprueba si se cumple una condición y, si se cumple, ejecuta una acción. Si no indicas condición, la acción se aplica a todas las líneas; si no indicas acción, la acción por defecto es imprimir la línea completa.
Con esta mecánica tan simple se pueden hacer auténticas barbaridades: desde mostrar solo algunas columnas de ps o df, hasta calcular totales, filtrar por patrones complejos con expresiones regulares, sustituir texto, formatear informes, trabajar con ficheros CSV o incluso escribir scripts de varias decenas de líneas.
Aunque awk puede recordar un poco a grep o sed, su enfoque es más estructurado: piensa en líneas como registros y en palabras (o campos) como columnas, con variables internas y un mini lenguaje que lo hace ideal para procesar datos tabulares de forma rápida.
En la práctica, si quieres empezar a escribir scripts de shell con cara y ojos, es casi obligatorio conocer awk junto a otras utilidades como sed, grep, cut y compañía. Son los ladrillos básicos del procesamiento de texto en Linux.
Instalar y ejecutar awk (gawk) en tu sistema
En la mayoría de distribuciones GNU/Linux modernos, awk ya viene instalado por defecto, normalmente en la variante GNU awk (gawk). Puedes comprobarlo con:
awk --version
Si por lo que sea no lo tienes instalado, en Debian, Ubuntu y derivadas puedes usar el gestor de paquetes:
sudo apt update && sudo apt install gawk
En macOS también lo tienes disponible. Puedes usar la versión del sistema o instalar una versión actualizada con Homebrew:
brew install gawk
Una vez instalado, awk se utiliza siempre con la misma idea: le pasas instrucciones entre comillas simples y un archivo (o conectas la salida de otro comando por tubería). Por ejemplo:
awk '{print}' archivo.txt
También puedes usar awk como intérprete de scripts, indicando la ruta al ejecutable en la primera línea del fichero:
#!/usr/bin/awk -f
y luego ejecutando el script directamente o con awk -f script.awk.
Sintaxis básica: patrones y acciones

La estructura mínima de awk es:
awk 'patrón { acción }' fichero
Cada línea del archivo se compara con el patrón. Si coincide, se ejecuta la acción entre llaves. Si omites el patrón, la acción se aplica a todas las líneas. Algunas ideas clave:
Variables especiales para referirte a cada línea:
$0: la línea completa.$1, $2, $3, …: campos (columnas) de la línea, separados por el delimitador definido.NF: número de campos en la línea actual.NR: número de registro actual (número de línea global).FNR: número de línea dentro del archivo actual, útil cuando procesas varios ficheros.
Instrucciones especiales:
BEGIN { … }: bloque que se ejecuta antes de leer ninguna línea.END { … }: bloque que se ejecuta al terminar de procesar todas las líneas.
Comandos de salida más comunes:
print: imprime argumentos separados por el separador de salida (OFS, por defecto un espacio).printf: similar aprintfen C, permite dar formato detallado sin añadir salto de línea automático.
Ejemplo mínimo para imprimir un archivo tal cual, como si fuera cat:
awk '{print}' archivo.txt
O si quieres que muestre también la longitud de cada línea:
awk '{print length, "\t", $0}' archivo.txt
Trabajar con columnas y separadores en awk
Uno de los usos estrella de awk es manipular columnas de salidas de comandos como ps, df o ficheros como /etc/passwd. Por defecto, awk considera como separador cualquier espacio o tabulación, pero puedes usar prácticamente cualquier delimitador.
Seleccionar columnas concretas
Imagina la salida de ps con varias columnas (PID, TTY, TIME, CMD…). Si solo quieres ver los PID, bastaría con:
ps | awk '{print $1}'
Si te interesa la segunda columna (por ejemplo, el TTY):
ps | awk '{print $2}'
Y si quieres saltarte la primera línea (la cabecera), puedes filtrar por número de registro:
ps | awk 'NR>1 {print $1}'
La idea es muy simple: cada número después del símbolo $ hace referencia a la columna correspondiente, siempre respecto al separador actual.
Cambiar el delimitador con -F y con FS
Muchos archivos del sistema no están separados por espacios, sino por otros símbolos. Un clásico es /etc/passwd, donde los campos están separados por :. Para tratar ese archivo por columnas, tienes dos opciones: la opción -F en la línea de comandos, o la variable FS dentro de un bloque BEGIN.
Usando -F en la línea de comandos:
cat /etc/passwd | awk -F ":" '{print $1}'
En este ejemplo se muestran solo los nombres de usuario (primer campo) porque el separador es ahora :. Si quieres también el UID y el GID (campos 3 y 4), basta con:
cat /etc/passwd | awk -F ":" '{print $1, $3, $4}'
El problema de este comando es que la salida sale pegada si no defines separadores explícitos, así que puedes añadir espacios o tabulaciones manualmente:
cat /etc/passwd | awk -F ":" '{print $1 " " $3 " " $4}'
Si quieres un resultado más tabulado, puedes usar \t para insertar tabulaciones:
cat /etc/passwd | awk -F ":" '{print $1 "\t" $3 "\t" $4}'
La alternativa con FS en un bloque BEGIN te permite fijar el separador dentro del propio script awk:
cat /etc/passwd | awk 'BEGIN { FS=":" } {print $1 "\t" $3 "\t" $4}'
Ambos enfoques son equivalentes funcionalmente, aunque usar BEGIN {FS=...} suele ser más limpio cuando escribes scripts.awk reutilizables.
FS y OFS: separadores de entrada y salida
Además de FS (Field Separator), awk dispone de OFS (Output Field Separator), que define cómo se separan los campos cuando usas print con comas:
cat /etc/passwd | awk 'BEGIN { FS=":"; OFS=" - " } {print $1, $3, $4}'
En este caso, lees con : pero escribes con - , generando una salida tipo:
root - 0 - 0
daemon - 1 - 1
...
Esta combinación FS/OFS es muy útil para “reformatear” datos, por ejemplo, para convertir de un formato a otro o para preparar salidas legibles que luego exportas a otro sistema.
Obtener el último campo con $NF (y los anteriores)
En muchas salidas de comandos, el campo que te interesa está al final, pero el número exacto de columnas varía. Es ahí donde $NF (Number of Fields) te simplifica la vida: es siempre el último campo de la línea actual.
Por ejemplo, en /etc/shells las rutas a shells válidas aparecen al final de cada línea, a veces en la segunda columna, otras en la tercera, etc. Para imprimir solo el nombre de la shell (la parte posterior a la última barra):
awk -F "/" '/^\// {print $NF}' /etc/shells
Si luego quieres quedarte solo con valores únicos (sin duplicados), puedes encadenar con uniq:
awk -F "/" '/^\// {print $NF}' /etc/shells | uniq
Y si lo que te interesa es el penúltimo elemento del camino (por ejemplo el directorio anterior), puedes usar $(NF-1) o $(NF-2):
awk -F "/" '/^\// {print $(NF-1)}' /etc/shells
awk -F "/" '/^\// {print $(NF-2)}' /etc/shells
Filtrar líneas con patrones, longitud y condiciones lógicas
Awk brilla cuando quieres quedarte solo con ciertas filas basándote en patrones de texto, columnas concretas o condiciones numéricas. Combina expresiones regulares, operadores lógicos y funciones como length para hacer filtros muy precisos.
Filtrar por patrones y expresiones regulares
La forma más directa de filtrar por contenido es poner la expresión regular entre barras justo antes de las llaves:
awk '/patrón/ {print}' archivo.txt
Por ejemplo, con la salida de df puedes mostrar solo las líneas que empiezan por una barra (sistemas de ficheros montados):
df | awk '/^\// {print}'
Si quieres una partición concreta, por ejemplo /dev/sda5:
df | awk '/^\/dev\/sda5/ {print}'
También puedes filtrar por patrones al principio o al final de la línea usando ^ y $:
awk '/^tmpfs/ {print}' archivo.txt
awk '/\/shm$/ {print}' archivo.txt
Y combinar varios criterios con el operador lógico &&. Por ejemplo, líneas que empiecen por tmpfs y terminen en /dev/shm:
df | awk '/\/shm$/ && /^tmpfs/ {print}'
Filtrar por columnas y mostrar solo lo que interesa
Muchas veces no solo quieres filtrar líneas, sino también limitar columnas. Siguiendo con df -h, puedes mostrar solo sistemas de ficheros reales (^/) y luego quedarte con las columnas 1, 2 y 3:
df -h | awk '/^\// {print $1 "\t" $2 "\t" $3}'
Awk permite incluso operar con los campos sobre la marcha. Por ejemplo, sumar las columnas 2 y 3 (usados + disponibles) para ver una “capacidad total” calculada:
df -h | awk '/^\// {print $1 "\t" $2 + $3}'
Si quieres añadir la unidad “G” literal al final del resultado:
df -h | awk '/^\// {print $1 "\t" $2 + $3 "G"}'
Filtrar por longitud de línea con length()
La función length() mide el número de caracteres de una cadena. Normalmente se usa con $0 (línea completa), pero también puedes usarla con una columna concreta.
Para mostrar solo las líneas de /etc/shells con más de 9 caracteres:
awk 'length($0) > 9' /etc/shells
Si quieres ver para cada línea su longitud:
awk '{print length, "\t", $0}' /etc/shells
También puedes filtrar por longitud y luego imprimir solo la longitud:
awk 'length($0) > 9 {print length}' /etc/shells
Combinar varias condiciones con && y if
Además de usar expresiones regulares al principio, puedes escribir condiciones completas dentro del bloque usando if, operadores de comparación y lógicos.
Por ejemplo, mostrar solo líneas de df -h que empiecen por t y cuya columna 6 tenga más de 8 caracteres:
df -h | awk '/^t/ && length($6) > 8 {print $0}'
Otro caso típico es buscar procesos por el último campo (comando ejecutado) en la salida de ps -ef. El último campo es $NF, así que puedes usar:
ps -ef | awk '{ if ($NF == "firefox") print $0 }'
Si solo te importa el PID y el comando:
ps -ef | awk '{ if ($NF == "firefox") print $2, $NF }'
Controlar líneas con NR, rangos y longitud de campos
La variable NR (Number of Record) cuenta cuántas líneas se han leído hasta ahora (a nivel global). Esto permite cosas tan comunes como saltarse cabeceras, imprimir rangos de líneas concretas o mostrar solo la primera fila.
Contar líneas y mostrar solo la primera o la segunda
Para contar el número total de líneas de un archivo sin usar wc -l puedes hacer:
awk 'END {print NR}' archivo.txt
Si quieres imprimir solo la primera línea:
awk 'NR==1 {print}' archivo.txt
Y para mostrar la segunda línea únicamente:
awk 'NR==2 {print}' archivo.txt
Imprimir a partir de una línea concreta o un rango
Para mostrar todas las líneas a partir de la tercera puedes usar una condición sencilla con > o >=:
ps -aux | awk 'NR>2 {print}'
Si quieres un rango, por ejemplo líneas de la 2 a la 4 en /etc/shells:
cat /etc/shells | awk 'NR==2, NR==4 {print $0}'
También puedes imprimir el número de línea junto al contenido:
cat /etc/shells | awk 'NR==2, NR==4 {print NR, $0}'
Longitud de campos concretos
Además de medir la longitud de líneas completas, puedes comprobar la longitud de una columna específica. Por ejemplo, para ver cuántos caracteres tiene el sistema de ficheros (columna 1) en la salida de df -h:
df -h | awk '{print length($1) "\t" $1}'
Si quieres saltarte la cabecera (primera línea), añade NR>1:
df -h | awk 'NR>1 {print length($1) "\t" $1}'
Funciones útiles: substr, match, RSTART y RLENGTH
Awk incluye un buen surtido de funciones de texto. Dos de las más potentes para búsquedas avanzadas son substr y match, acompañada esta última de las variables RSTART y RLENGTH.
Recortar texto con substr()
La función substr(cadena, inicio) o substr(cadena, inicio, longitud) te permite extraer subcadenas. Por ejemplo, para eliminar los primeros 5 caracteres de cada línea de /etc/shells:
cat /etc/shells | awk '{print substr($0, 5)}'
Si no quieres procesar la primera línea (por ejemplo un comentario), puedes usar NR:
cat /etc/shells | awk 'NR>1 {print substr($0, 5)}'
Ten en cuenta que el primer parámetro es la cadena (habitualmente $0) y el segundo indica desde qué carácter quieres empezar a mostrar.
Localizar patrones con match(), RSTART y RLENGTH
La función match(cadena, /regex/) busca una expresión regular dentro de la cadena. Si encuentra coincidencia, devuelve la posición inicial (basada en 1) y rellena dos variables:
RSTART: posición donde empieza el patrón encontrado.RLENGTH: longitud de la coincidencia.
Por ejemplo, para todas las líneas de ps -aux que contengan “cpu”, puedes mostrar la línea completa y la posición donde se encuentra el patrón:
ps -aux | awk 'match($0, /cpu/) {print $0 " Contiene \"cpu\" en la posición " RSTART}'
Si además quieres saber cuánto mide el patrón encontrado, basta con usar RLENGTH en la salida:
ps -aux | awk 'match($0, /cpu/) {print $0 " Posición=" RSTART " Longitud=" RLENGTH}'
Este tipo de búsquedas se usan mucho en análisis de texto y bioinformática, por ejemplo sobre ficheros FASTA, donde te interesa localizar motivos concretos en secuencias.
Operaciones matemáticas y variables en awk
Awk no se limita a mostrar texto: permite realizar operaciones numéricas directamente sobre campos, variables internas o valores que le pases desde la línea de comandos o desde el entorno de la shell.
Definir variables con -v y usarlas en BEGIN
Puedes declarar variables con la opción -v al invocar awk. Por ejemplo, multiplicar dos números fijos:
awk -v a="10" -v b="20" 'BEGIN {print "La multiplicación de a x b es", a*b}'
También es posible pasar valores de variables de tu shell. Si en bash haces:
a=1.5
b=4
Luego puedes usarlos en awk así:
awk -v a="$a" -v b="$b" 'BEGIN {print "La multiplicación de a x b es", a*b}'
El bloque BEGIN se utiliza aquí porque no estamos procesando ningún archivo, solo queremos ejecutar código una vez y mostrar un resultado.
Funciones matemáticas: sqrt y bucles for
Awk incorpora varias funciones matemáticas estándar, como sqrt() para raíces cuadradas. Por ejemplo, la raíz de 400:
awk 'BEGIN {print sqrt(400)}'
También puedes combinarla con bucles for para generar listados completos:
awk 'BEGIN { for(i=1; i<=10; i++) print "La raíz cuadrada de", i*i, "es", i }'
O recorrer valores decimales de 0 a 1 con pequeños incrementos:
awk 'BEGIN { for(i=0; i<=1; i=i+0.00001) print "La raíz cuadrada de", i*i, "es", i }'
Este tipo de estructuras hacen que awk se parezca mucho a un lenguaje tradicional, aunque su terreno natural siga siendo el texto en columnas.
Escribir y ejecutar scripts completos en awk
Cuando los comandos awk empiezan a ser largos o quieres reutilizar transformaciones complejas, lo sensato es guardarlos en un archivo de script con extensión .awk (aunque no es obligatorio).
Un ejemplo típico consiste en procesar la salida de df para mostrar solo ciertas entradas que cumplan condiciones sobre el espacio disponible y formatear resultados como una pequeña tabla.
Imagina que quieres lo siguiente:
- Mostrar solo sistemas de ficheros cuyo nombre empiece por “t” (por ejemplo
tmpfs). - Filtrar aquellos con capacidad disponible (columna 4) superior a 6000K.
- Imprimir solo la unidad (columna 1) y la suma de columnas 2 y 3 como espacio total aproximado.
Puedes crear un script llamado capacidad.awk con un contenido similar a este (adaptado y simplificado):
#!/usr/bin/awk -f
BEGIN { printf "%s\n", "Voy a extraer las partes que me interesan del comando df" }
BEGIN { printf "%s\t%s\n", "Unidad", "Capacidad disponible" }
/^t/ && $4 > 6000 {print $1 "\t" $2 + $3 "K"}
Y luego ejecutarlo encadenando la salida de df:
df | awk -f capacidad.awk
Si quieres mejorar el aspecto de la tabla, puedes sustituir print por printf y usar formatos como %-12s (texto justificado a la izquierda en 12 caracteres) o %-23d (número decimal en 23 caracteres). Así controlas perfectamente el alineado de columnas.
Buscar y reemplazar texto con gsub()
Awk también puede hacer sustituciones de texto similares a las que harías con sed, usando la función gsub() (global substitute).
La sintaxis general es:
gsub("texto_o_regex_a_buscar", "texto_de_reemplazo", destino)
Por ejemplo, supón un fichero geekland.txt con el texto “Geekland es el mejor blog, de tecnología” y quieres cambiar la G inicial por g:
awk '{ gsub("G", "g", $0); print $0 }' geekland.txt
Si no especificas el tercer parámetro, la búsqueda se hace sobre $0 por defecto, pero es muy habitual limitar el reemplazo a una sola columna:
df -h | awk '{ gsub("M", "G", $2); print $2 }'
En este caso, cambiamos la unidad M por G en la columna 2 solamente. Si quieres mostrar también la columna 1 bien alineada, puedes combinarlo con printf:
df -h | awk '{ gsub("M", "G", $2); printf "%-12s %-12s\n", $1, $2 }'
Este patrón de “modifico una columna y luego imprimo formateado” es extremadamente útil en informes, migraciones de datos o limpiezas rápidas sobre salidas de comandos.
Usos adicionales: cat con esteroides y ejecución de comandos
Aunque pueda parecer una tontería, awk puede hacer las veces de cat mejorado, ya que puede mostrar un archivo mientras añade información extra (números de línea, longitudes, etc.).
Un uso trivial sería:
awk '{print}' functions.php
Pero puedes también numerar líneas o aplicar cualquier filtro sin necesidad de usar más herramientas.
Otra curiosidad interesante es que awk puede ejecutar comandos de sistema mediante la función system(). Por ejemplo, mostrar el directorio actual:
awk 'BEGIN { system("pwd") }'
No es lo más habitual en scripts sencillos, pero viene bien saber que existe cuando estás montando herramientas más complejas basadas en awk.
Awk se convierte en una navaja suiza para el texto en Linux: te permite filtrar líneas, seleccionar y combinar columnas, sustituir fragmentos, medir longitudes, localizar patrones, sumar campos, generar pequeños informes formateados y hasta construir scripts completos que procesan salidas de otros comandos. Una vez lo dominas un poco, se vuelve una herramienta de uso diario siempre que trabajas con terminal y datos estructurados.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.