Comando awk: imprimir campos, el delimitador -F y patrones condicionales
El comando awk es una herramienta de Linux que lee un archivo de texto línea por línea, divide cada línea en campos por los espacios o por el delimitador que indiques, y selecciona solo los campos de las líneas que cumplen una condición para mostrarlos o calcular con ellos. En un servidor AlmaLinux 9, contamos las solicitudes por IP de origen y los casos por código de estado de un archivo de ejemplo de registro de acceso de un servidor web con una sola línea unida a sort mediante una tubería, y resultó que las tres respuestas 404 de las doce líneas eran solicitudes a wp-login.php y .env desde una misma IP.
La salida siguiente se obtuvo con la cuenta root dentro de una carpeta de trabajo en un servidor AlmaLinux 9.8. El registro de acceso, la lista de cuentas, los registros de ventas y el archivo de puntuaciones son archivos de ejemplo creados para las pruebas, y las direcciones IP y los nombres de cuenta que contienen también son valores de ejemplo.
1️⃣ Uso básico del comando awk
awk divide cada línea leída por los espacios y numera los campos desde la izquierda como $1, $2, $3. Lo comprobamos con scores.txt, donde el nombre, el resultado y la puntuación están separados por espacios.
cat scores.txtalice pass 82
bob fail 47
carol pass 91
dave pass 68
erin fail 55Las llaves dentro de las comillas simples contienen la acción que se ejecuta en cada línea, y si después de print enumeras números de campo separados por comas, solo salen esos campos. Al mostrar los campos primero y tercero quedan solo el nombre y la puntuación.
awk '{print $1, $3}' scores.txtalice 82
bob 47
carol 91
dave 68
erin 55Si quitas la coma entre campos y escribes $1 $3, los dos valores salen unidos sin espacio. La coma de print inserta el separador de salida (un espacio por defecto), y los valores escritos juntos sin coma se unen en una sola cadena.
awk '{print $1 $3}' scores.txtalice82
bob47
carol91
dave68
erin55NR es el número de la línea leída hasta el momento, y NF es el número de campos de esa línea. $NF indica el último campo, así que puedes elegir la última columna aunque el número de campos cambie de una línea a otra.
awk '{print NR, NF, $NF}' scores.txt1 3 82
2 3 47
3 3 91
4 3 68
5 3 55El registro de acceso de un servidor web también está separado por espacios, así que los campos se eligen de la misma forma. Los números de campo de la primera línea del registro de prueba son los siguientes.
| Campo | Valor en la primera línea | Significado |
|---|---|---|
| $1 | 192.0.2.10 | IP de origen |
| $4 | [29/Oct/2026:00:01:12 | Fecha y hora de la solicitud |
| $6 | "GET | Método de la solicitud (con comillas dobles delante) |
| $7 | /index.html | URL de la solicitud |
| $9 | 200 | Código de estado |
| $10 | 5120 | Bytes enviados |
| $11 | "-" | Página anterior (Referer) |
| $12~$15 | "Mozilla/5.0 (X11; Linux x86_64)" | Agente de usuario (se divide en cada espacio) |
Mostramos $1, $7 y $9, que corresponden a la IP de origen, la URL de la solicitud y el código de estado.
awk '{print $1, $7, $9}' access.log192.0.2.10 /index.html 200
198.51.100.7 /about.html 200
192.0.2.10 /images/logo.png 200
203.0.113.25 /wp-login.php 404
203.0.113.25 /wp-login.php 404
192.0.2.10 /contact.html 200
198.51.100.7 /old-page.html 301
203.0.113.25 /.env 404
192.0.2.44 /index.html 200
198.51.100.7 /api/search?q=awk 500
192.0.2.44 /images/logo.png 304
192.0.2.10 /index.html 200Una columna con espacios en su valor, como el agente de usuario, se divide en varios campos. NF fue 15 en las tres primeras líneas, y $NF es el último fragmento del agente de usuario.
awk '{print NF, $NF}' access.log | head -315 x86_64)"
15 x86_64)"
15 x86_64)"2️⃣ Indicar el delimitador con awk -F
En un archivo cuyas columnas se separan con un símbolo que no es el espacio, escribe ese símbolo después de -F. Al mostrar $1 sin -F en la lista de cuentas users.txt, creada con la misma forma que /etc/passwd, la mayoría de las líneas salieron enteras.
awk '{print $1}' users.txtroot:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
nobody:x:65534:65534:Kernel
user:x:1000:1000:Example
deploy:x:1001:1001:Deploy
backup:x:1002:1002::/home/backup:/sbin/nologinEl delimitador por defecto es el espacio, así que una línea unida solo por dos puntos tiene un único campo. Solo las líneas nobody, user y deploy, que tienen un espacio en la columna de descripción, se cortan en ese espacio.
Si indicas los dos puntos como delimitador con -F:, se separan el nombre de cuenta ($1) y el shell de inicio de sesión ($7).
awk -F: '{print $1, $7}' users.txtroot /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
nobody /sbin/nologin
user /bin/bash
deploy /bin/bash
backup /sbin/nologinLos archivos CSV separados por comas se dividen con -F,. Al mostrar el artículo y la cantidad de los registros de ventas sales.csv, la cabecera de la primera línea (item qty) se divide igual y aparece también.
awk -F, '{print $2, $3}' sales.csvitem qty
keyboard 2
mouse 5
monitor 1
keyboard 1
cable 10
mouse 2
monitor 2-F, no sirve para CSV con comas dentro de columnas entre comillas dobles. En quoted.csv, que tiene comas en la columna del artículo, los campos también se dividen en las comas entre comillas, y en el segundo campo queda solo la primera parte del nombre del artículo.
awk -F, '{print $2}' quoted.csvitem
"cable
keyboardPara estos archivos, el manual oficial de GNU Awk explica cómo usar la variable FPAT. Si en lugar del delimitador escribes la forma de un campo como expresión regular, la columna entre comillas sale como un solo campo.
awk -v FPAT='([^,]*)|("[^"]*")' '{print $2}' quoted.csvitem
"cable, usb"
keyboardPara usar varios delimitadores, escríbelos como expresión regular entre corchetes. Si indicas como delimitadores los dos puntos y la barra, $NF pasa a ser el último nombre de la ruta del shell de inicio de sesión (bash, nologin).
awk -F'[:/]' '{print $1, $NF}' users.txtroot bash
bin nologin
daemon nologin
nobody nologin
user bash
deploy bash
backup nologin3️⃣ Patrones condicionales del comando awk
Aunque elijas campos, se muestran todas las líneas, así que para dejar solo las que necesitas pon una condición (patrón) antes de las llaves. Una cadena entre barras selecciona solo las líneas que la contienen, y si omites la acción se muestra la línea entera.
awk '/wp-login/' access.log203.0.113.25 - - [29/Oct/2026:00:04:51 +0000] "POST /wp-login.php HTTP/1.1" 404 196 "-" "Mozilla/5.0 (X11; Linux x86_64)"
203.0.113.25 - - [29/Oct/2026:00:04:52 +0000] "POST /wp-login.php HTTP/1.1" 404 196 "-" "Mozilla/5.0 (X11; Linux x86_64)"Las líneas seleccionadas son las mismas que con el comando grep, y awk puede elegir directamente los campos de esas líneas y mostrarlos. Si pasas a awk por una tubería las mismas dos líneas seleccionadas con grep, quedan solo la IP y el código de estado.
grep wp-login access.log | awk '{print $1, $9}'203.0.113.25 404
203.0.113.25 404Los valores de los campos se comparan con ==, !=, >, >=, <, <=. Seleccionamos solo las líneas cuyo código de estado ($9) es 404 y mostramos la IP y la URL de la solicitud.
awk '$9 == 404 {print $1, $7}' access.log203.0.113.25 /wp-login.php
203.0.113.25 /wp-login.php
203.0.113.25 /.envAl comparar con una cadena, pon el valor entre comillas dobles. Seleccionamos solo los nombres cuyo segundo campo es pass.
awk '$2 == "pass" {print $1}' scores.txtalice
carol
daveLa comparación numérica sirve para seleccionar por rangos, como con los números de cuenta (UID). Al seleccionar las cuentas con UID de 1000 o más, junto a las cuentas normales entra también nobody, cuyo UID es 65534.
awk -F: '$3 >= 1000 {print $1, $3}' users.txtnobody 65534
user 1000
deploy 1001
backup 1002Dos condiciones se unen con &&. Al añadir la condición de menos de 65534, nobody desaparece y quedan solo las tres cuentas normales y sus carpetas personales.
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $6}' users.txtuser /home/user
deploy /home/deploy
backup /home/backup[~] comprueba si un campo coincide con una expresión regular, y [!~] si no coincide. Al seleccionar por separado las cuentas cuyo shell de inicio de sesión ($7) termina en bash y las que no son nologin, salen las mismas tres cuentas.
awk -F: '$7 ~ /bash$/ {print $1}' users.txtroot
user
deployawk -F: '$7 !~ /nologin/ {print $1, $7}' users.txtroot /bin/bash
user /bin/bash
deploy /bin/bashLa condición NR selecciona por número de línea. Con NR > 1 se quita la cabecera del CSV y quedan solo los registros de ventas.
awk -F, 'NR > 1 {print $2, $3}' sales.csvkeyboard 2
mouse 5
monitor 1
keyboard 1
cable 10
mouse 2
monitor 2La salida de otros comandos también se puede pasar por una tubería y dividir igual. Al elegir el tamaño ($5) y el nombre ($9) en la salida de ls -l, la primera línea salió vacía, porque la primera línea de ls -l, [total 24], no tiene campos quinto ni noveno.
ls -l | awk '{print $5, $9}'
1567 access.log
79 quoted.csv
207 sales.csv
85 scores-copy.txt
85 scores.txt
315 users.txtAl añadir NR > 1 desaparece la primera línea y quedan solo los tamaños y los nombres de archivo.
ls -l | awk 'NR > 1 {print $5, $9}'1567 access.log
79 quoted.csv
207 sales.csv
85 scores-copy.txt
85 scores.txt
315 users.txt4️⃣ BEGIN y END de awk, sumas y promedios
El bloque BEGIN se ejecuta una vez antes de leer la primera línea, y el bloque END una vez después de procesar la última. Para una suma, añade a una variable en cada línea y muéstrala en END. El diagrama siguiente muestra el orden que sigue awk en cada línea al sumar los importes de los registros de ventas.
$ awk -F, 'NR > 1 {t += $3 * $4} END {printf "total %.2f\n", t}' sales.csvLa suma de todos los bytes enviados ($10) del registro de acceso fue de 41298 bytes. Una variable usada por primera vez empieza vacía (0 como número), así que no hace falta ponerla a 0.
awk '{sum += $10} END {print sum}' access.log41298Si muestras la suma en la acción de cada línea en lugar de en END, cada línea muestra el total acumulado hasta ese momento. Si cada vez que sumas a t la cantidad por el precio muestras el número de línea y t, salen siete líneas sin la cabecera, y el 886.3 de la última línea es el total general.
awk -F, 'NR > 1 {t += $3 * $4; print NR, t}' sales.csv2 90
3 189.5
4 378.5
5 423.5
6 468.5
7 508.3
8 886.3El promedio se calcula en END dividiendo la suma entre el número de líneas. La suma de las cinco puntuaciones fue 343 y el promedio 68.6.
awk '{total += $3; n++} END {print total, n, total / n}' scores.txt343 5 68.6BEGIN sirve para mostrar una vez una línea de cabecera sobre los resultados. Sobre los artículos e importes (cantidad × precio unitario) aparece una sola vez la línea item total.
awk -F, 'BEGIN {print "item", "total"} NR > 1 {print $2, $3 * $4}' sales.csvitem total
keyboard 90
mouse 99.5
monitor 189
keyboard 45
cable 45
mouse 39.8
monitor 378El separador de salida se cambia con la variable OFS en BEGIN. Al poner OFS como coma, donde están las comas de print entra una coma en lugar de un espacio, y la lista de cuentas sale en forma de CSV.
awk 'BEGIN {FS = ":"; OFS = ","} {print $1, $3, $7}' users.txtroot,0,/bin/bash
bin,1,/sbin/nologin
daemon,2,/sbin/nologin
nobody,65534,/sbin/nologin
user,1000,/bin/bash
deploy,1001,/bin/bash
backup,1002,/sbin/nologinPara alinear columnas usa printf. %-10s es una cadena alineada a la izquierda en 10 posiciones, %3d es un entero de 3 posiciones y %8.2f es un número en 8 posiciones con dos decimales.
awk -F, 'NR > 1 {printf "%-10s %8.2f\n", $2, $3, $3 * $4}' sales.csvkeyboard 2 90.00
mouse 5 99.50
monitor 1 189.00
keyboard 1 45.00
cable 10 45.00
mouse 2 39.80
monitor 2 378.00A diferencia de print, printf no cambia de línea, así que pon [\n] al final del formato. Sin [\n], los nombres de los artículos salen seguidos en una línea.
awk -F, 'NR > 1 {printf "%s ", $2}' sales.csvkeyboard mouse monitor keyboard cable mouse monitor5️⃣ Análisis de registros y opciones del comando awk
🔲 Análisis de registros
Sumar a una sola variable da un solo total, así que para contar por IP de origen o por código de estado, reúne los valores en un array. n[$1]++ suma 1 a la posición del array con la IP como clave, y el for (ip in n) de END saca las posiciones una a una.
awk '{n[$1]++} END {for (ip in n) print n[ip], ip}' access.log | sort -rn4 192.0.2.10
3 203.0.113.25
3 198.51.100.7
2 192.0.2.44El orden en que for (ip in n) las saca no está definido (según el manual de GNU Awk), así que las ordenamos por número de solicitudes con sort -rn. 192.0.2.10 fue la que más tuvo, con 4.
Las respuestas por código de estado se cuentan igual. Hubo 3 respuestas 404 y 1 respuesta 500.
awk '{n[$9]++} END {for (s in n) print s, n[s]}' access.log | sort200 6
301 1
304 1
404 3
500 1Si extraes solo los códigos de estado y los pasas a sort y uniq -c, salen los mismos recuentos.
awk '{print $9}' access.log | sort | uniq -c 6 200
1 301
1 304
3 404
1 500Para ver solo las respuestas de error, pon una condición en el código de estado. Las líneas de 400 o más fueron tres solicitudes que buscaban wp-login.php y .env, y un error 500.
awk '$9 >= 400 {print $9, $1, $7}' access.log404 203.0.113.25 /wp-login.php
404 203.0.113.25 /wp-login.php
404 203.0.113.25 /.env
500 198.51.100.7 /api/search?q=awkEl total de bytes enviados por IP también se calcula sumando en un array. 192.0.2.10 fue la que más recibió, con 31340 bytes.
awk '{b[$1] += $10} END {for (ip in b) print b[ip], ip}' access.log | sort -rn31340 192.0.2.10
5120 192.0.2.44
4250 198.51.100.7
588 203.0.113.25El campo de hora ($4) se puede comparar como cadena. Entre líneas con la misma fecha y formato, el orden de cadena coincide con el orden horario, así que seleccionamos solo las cuatro solicitudes desde las 00:05 hasta antes de las 00:10.
awk '$4 >= "[29/Oct/2026:00:05" && $4 < "[29/Oct/2026:00:10" {print $4, $7}' access.log[29/Oct/2026:00:05:30 /contact.html
[29/Oct/2026:00:07:02 /old-page.html
[29/Oct/2026:00:07:15 /.env
[29/Oct/2026:00:09:48 /index.html🔲 Opciones del comando awk
📌 Opciones principales: resultados de este artículo
| Opción | Tarea | Resultado en este artículo |
|---|---|---|
| -F fs | Indica el separador de campos de entrada | -F: separa el nombre de cuenta ($1) y el shell de inicio de sesión ($7) de users.txt; -F, muestra el artículo y la cantidad de sales.csv junto con la cabecera (item qty) |
| -v var=val | Asigna un valor a una variable antes de ejecutar el programa | Al pasar la variable de shell min con -v min=$min salen seis líneas con 1000 bytes enviados o más; con -v FPAT=…, la columna entre comillas de quoted.csv sale como un solo campo |
| -i inplace | Guarda la salida en el archivo original en lugar de la pantalla | Tras ejecutar gawk -i inplace, no aparece nada en pantalla y la copia de scores.txt pasa a dos columnas, nombre y puntuación; si añades -v inplace::suffix=.bak, el contenido anterior queda en un archivo .bak |
| --version | Muestra la información de versión | La primera línea de [awk --version] muestra la versión GNU Awk 5 |
📎 Otras opciones: según el manual oficial
| Opción | Tarea |
|---|---|
| -f program-file | Lee el programa AWK de un archivo en lugar del primer argumento de la línea de comandos; -f se puede indicar varias veces |
| -e program-text | Usa el texto de la línea de comandos como código del programa AWK; se puede usar con funciones de biblioteca cargadas con -f o --include |
| -E file | Parecida a -f, pero se procesa al final y bloquea las asignaciones de variables en la línea de comandos; para scripts #! |
| --traditional | Ejecuta en modo de compatibilidad, sin reconocer las extensiones de GNU |
| --posix | Activa el modo de compatibilidad y añade más restricciones; por ejemplo, no reconoce func, sinónimo de function |
| --lint | Avisa de construcciones dudosas o difíciles de llevar a otras implementaciones de AWK; con --lint=fatal, los avisos pasan a ser errores fatales |
| --dump-variables | Escribe en un archivo una lista ordenada de las variables globales con sus tipos y valores finales; awkvars.out si no se indica archivo |
🔲 Simulador del comando awk
En el simulador de abajo puedes escribir tú mismo comandos awk sobre los mismos archivos de prueba.
🔢 FAQ & contenido recomendado
Ordenar
Comando sort de Linux: ordenar archivos
El comando sort ordena el contenido de un archivo alfabéticamente o por valor numérico. Úsalo a continuación para ver los totales de awk de mayor a menor.
Quitar duplicados
Comando uniq de Linux
El comando uniq reduce a una las líneas iguales seguidas y, con -c, cuenta cuántas veces se repitieron.
Ver archivos
Comando head y comando tail de Linux
Los comandos head y tail muestran solo las primeras o últimas líneas de un archivo. Se usan a menudo para revisar el registro de acceso de un servidor.
ℹ️ Aviso de afiliados
El contenido de este sitio incluye enlaces de afiliado. Cuando un visitante compra un producto o servicio a través de uno de ellos, el sitio recibe una comisión del vendedor. El importe que paga el comprador(baja durante las promociones ↓)no aumenta. Los precios, descuentos y existencias publicados corresponden al momento de redacción y pueden variar, así que confírmalos con el vendedor antes de comprar. Los productos se eligen y evalúan con criterios propios, y las comisiones no influyen en el orden ni en el contenido de las reseñas.