Comando awk de Linux: Procesamiento de texto

LinuxLinuxBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Bienvenido al mundo del procesamiento de texto con AWK. En este laboratorio, aprenderá cómo utilizar el comando awk para analizar archivos de registro, una tarea común para administradores de sistemas y analistas de datos. AWK es una herramienta poderosa para procesar datos de texto estructurados en Linux, que le permite extraer, filtrar y transformar información de manera eficiente.

Imagina que eres un administrador de sistemas junior encargado de analizar los registros del servidor para identificar posibles amenazas de seguridad y problemas de rendimiento. El comando awk será tu herramienta principal para esta tarea, lo que te permitirá examinar rápidamente grandes archivos de registro y extraer información significativa.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) linux(("Linux")) -.-> linux/TextProcessingGroup(["Text Processing"]) linux/BasicFileOperationsGroup -.-> linux/touch("File Creating/Updating") linux/BasicFileOperationsGroup -.-> linux/cat("File Concatenating") linux/BasicFileOperationsGroup -.-> linux/head("File Beginning Display") linux/TextProcessingGroup -.-> linux/grep("Pattern Searching") linux/TextProcessingGroup -.-> linux/awk("Text Processing") linux/TextProcessingGroup -.-> linux/sort("Text Sorting") linux/TextProcessingGroup -.-> linux/uniq("Duplicate Filtering") subgraph Lab Skills linux/touch -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/cat -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/head -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/grep -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/awk -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/sort -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} linux/uniq -.-> lab-388493{{"Comando awk de Linux: Procesamiento de texto"}} end

Examinando el archivo de registro

Comencemos examinando el contenido de nuestro archivo de registro de muestra. Este archivo contiene registros de acceso a servidores simulados que analizaremos a lo largo de este laboratorio.

Primero, navega al directorio del proyecto:

cd ~/project

Ahora, veamos las primeras líneas del archivo de registro:

head -n 5 server_logs.txt

Deberías ver una salida similar a esta:

2023-08-01 08:15:23 192.168.1.100 GET /index.html 200
2023-08-01 08:16:45 192.168.1.101 GET /about.html 200
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 08:18:12 192.168.1.103 GET /products.html 404
2023-08-01 08:19:05 192.168.1.104 GET /services.html 200

Este archivo de registro contiene información sobre las solicitudes al servidor, incluyendo la fecha y hora, la dirección IP, el método HTTP, el recurso solicitado y el código de estado.

Uso básico de AWK - Imprimir campos específicos

Ahora que hemos visto la estructura de nuestro archivo de registro, usemos AWK para extraer información específica. Por defecto, AWK divide cada línea en campos basados en espacios en blanco. Podemos referirnos a estos campos usando $1, $2, etc., donde $1 es el primer campo, $2 es el segundo, y así sucesivamente.

Extraigamos las direcciones IP (el tercer campo) de nuestro archivo de registro:

awk '{print $3}' server_logs.txt | head -n 5

Deberías ver una salida similar a esta:

192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104

En este comando:

  • awk '{print $3}' le dice a AWK que imprima el tercer campo de cada línea.
  • Redirigimos (|) la salida a head -n 5 para limitar la visualización a las primeras 5 líneas.

Ahora, imprimamos tanto la dirección IP como el recurso solicitado:

awk '{print $3, $5}' server_logs.txt | head -n 5

Salida:

192.168.1.100 /index.html
192.168.1.101 /about.html
192.168.1.102 /login.php
192.168.1.103 /products.html
192.168.1.104 /services.html

Aquí, estamos imprimiendo el tercer campo (dirección IP) y el quinto campo (recurso solicitado) de cada línea.

Filtrado de entradas de registro

Una de las fortalezas de AWK es su capacidad para filtrar datos basados en condiciones. Usemos esta función para encontrar todas las solicitudes POST en nuestro archivo de registro, ya que estas pueden ser más sensibles desde el punto de vista de la seguridad que las solicitudes GET.

Ejecute el siguiente comando:

awk '$4 == "POST" {print $0}' server_logs.txt

Desglosemos la sintaxis de este comando para entender cómo funciona el filtrado en AWK:

  1. $4 == "POST" - Este es un patrón o condición que AWK evalúa para cada línea:

    • $4 se refiere al cuarto campo de la línea actual (en nuestro archivo de registro, este es el método HTTP)
    • == es el operador de igualdad que verifica si dos valores son iguales
    • "POST" es la cadena contra la que estamos comparando
  2. {print $0} - Esta es la acción que AWK realiza cuando la condición es verdadera:

    • Las llaves {} encierran la acción
    • print es el comando para mostrar texto
    • $0 representa la línea actual completa (todos los campos)

La estructura del comando sigue el patrón de AWK: condición {acción}. AWK lee cada línea, y si la condición se evalúa como verdadera, realiza la acción. Si no se especifica ninguna condición (como en nuestros ejemplos anteriores), la acción se realiza para cada línea.

Debería ver una salida similar a esta:

2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 09:23:45 192.168.1.110 POST /submit_form.php 200
2023-08-01 10:45:12 192.168.1.115 POST /upload.php 500

Ahora, encontremos todas las solicitudes que resultaron en un estado 404 (No encontrado):

awk '$6 == "404" {print $1, $2, $5}' server_logs.txt

Este comando sigue el mismo patrón pero con valores diferentes:

  • La condición $6 == "404" verifica si el sexto campo (código de estado) es igual a 404
  • La acción {print $1, $2, $5} muestra solo campos específicos:
    • $1 - Primer campo (fecha)
    • $2 - Segundo campo (hora)
    • $5 - Quinto campo (recurso solicitado)

Esta impresión selectiva le permite centrarse solo en la información que necesita.

Salida:

2023-08-01 08:18:12 /products.html
2023-08-01 09:30:18 /nonexistent.html
2023-08-01 11:05:30 /missing_page.html

Puede combinar múltiples condiciones usando operadores lógicos:

  • && para AND (ambas condiciones deben ser verdaderas)
  • || para OR (al menos una condición debe ser verdadera)
  • ! para NOT (niega una condición)

Por ejemplo, para encontrar todas las solicitudes POST que resultaron en un error (código de estado >= 400):

awk '$4 == "POST" && $6 >= 400 {print $0}' server_logs.txt

Estos filtros pueden ayudarlo a identificar rápidamente posibles problemas o actividades sospechosas en los registros de su servidor.

Conteo y resumen de datos

AWK es excelente para contar ocurrencias y resumir datos. Usémoslo para contar el número de solicitudes para cada código de estado HTTP.

Ejecute este comando:

awk '{count[$6]++} END {for (code in count) print code, count[code]}' server_logs.txt | sort -n

Este comando es más complejo, así que analicémoslo paso a paso:

  1. {count[$6]++} - Esta es la acción principal realizada para cada línea:

    • count es un array (array asociativo o diccionario) que estamos creando
    • [$6] utiliza el valor del sexto campo (código de estado) como índice/clave del array
    • ++ es el operador de incremento, que agrega 1 al valor actual
    • Así, para cada línea, incrementamos el contador para el código de estado específico encontrado
  2. END {for (code in count) print code, count[code]} - Esto se ejecuta después de procesar todas las líneas:

    • END es un patrón especial que coincide con el final de la entrada
    • {...} contiene la acción a realizar después de procesar toda la entrada
    • for (code in count) es un bucle que itera a través de todas las claves del array count
    • print code, count[code] imprime cada código de estado y su conteo
  3. | sort -n - Envía la salida al comando sort, que ordena numéricamente

Cuando AWK procesa un array como count[$6]++, automáticamente:

  • Crea el array si no existe
  • Crea un nuevo elemento con valor 0 si la clave no existe
  • Luego incrementa el valor en 1

Debería ver una salida similar a esta:

200 3562
301 45
302 78
304 112
400 23
403 8
404 89
500 15

Este resumen le muestra rápidamente la distribución de los códigos de estado en su archivo de registro.

Ahora, encontremos los 5 recursos más accedidos:

awk '{count[$5]++} END {for (resource in count) print count[resource], resource}' server_logs.txt | sort -rn | head -n 5

Este comando sigue un patrón similar con algunos cambios:

  1. {count[$5]++} - Cuenta las ocurrencias del quinto campo (el recurso solicitado)
  2. END {for (resource in count) print count[resource], resource} - Después de procesar todas las líneas:
    • Imprime el conteo primero, seguido del recurso
    • Este cambio de orden facilita la ordenación numérica por conteo
  3. | sort -rn - Ordena numéricamente en orden inverso (los conteos más altos primero)
  4. | head -n 5 - Limita la salida a las primeras 5 líneas (los 5 mejores resultados)

Salida:

1823 /index.html
956 /about.html
743 /products.html
512 /services.html
298 /contact.html

Estos comandos AWK demuestran el poder de usar arrays para contar y resumir. Puedes adaptar este patrón para contar cualquier campo o combinación de campos en tus datos.

Por ejemplo, para contar el número de solicitudes por dirección IP:

awk '{count[$3]++} END {for (ip in count) print ip, count[ip]}' server_logs.txt

Para contar solicitudes por método y estado:

awk '{key=$4"-"$6; count[key]++} END {for (k in count) print k, count[k]}' server_logs.txt

Estos resúmenes pueden ayudarte a entender los patrones de tráfico e identificar recursos populares (o problemáticos) en tu servidor.

Creación de un informe sencillo

Para nuestra tarea final, creemos un informe HTML sencillo que resuma alguna información clave de nuestro archivo de registro. Utilizaremos un script AWK almacenado en un archivo separado para esta operación más compleja.

Primero, crea un archivo llamado log_report.awk con el siguiente contenido:

Consejo: Copia el contenido de abajo y pégalo en tu terminal para crear el archivo.

cat << 'EOF' > log_report.awk
BEGIN {
    print "<html><body>"
    print "<h1>Server Log Summary</h1>"
    total = 0
    errors = 0
}

{
    total++
    if ($6 >= 400) errors++
    ip_count[$3]++
    resource_count[$5]++
}

END {
    print "<p>Total requests: " total "</p>"
    print "<p>Error rate: " (errors/total) * 100 "%</p>"
    
    print "<h2>Top 5 IP Addresses</h2>"
    print "<ul>"
    for (ip in ip_count) {
        top_ips[ip] = ip_count[ip]
    }
    n = asort(top_ips, sorted_ips, "@val_num_desc")
    for (i = 1; i <= 5 && i <= n; i++) {
        for (ip in ip_count) {
            if (ip_count[ip] == sorted_ips[i]) {
                print "<li>" ip ": " ip_count[ip] " requests</li>"
                break
            }
        }
    }
    print "</ul>"
    
    print "<h2>Top 5 Requested Resources</h2>"
    print "<ul>"
    for (resource in resource_count) {
        top_resources[resource] = resource_count[resource]
    }
    n = asort(top_resources, sorted_resources, "@val_num_desc")
    for (i = 1; i <= 5 && i <= n; i++) {
        for (resource in resource_count) {
            if (resource_count[resource] == sorted_resources[i]) {
                print "<li>" resource ": " resource_count[resource] " requests</li>"
                break
            }
        }
    }
    print "</ul>"
    
    print "</body></html>"
}
EOF

Vamos a entender este script AWK sección por sección:

  1. Bloque BEGIN: Se ejecuta antes de procesar cualquier línea de entrada

    BEGIN {
        print "<html><body>"  ## Iniciar estructura HTML
        print "<h1>Server Log Summary</h1>"
        total = 0  ## Inicializar contador para solicitudes totales
        errors = 0  ## Inicializar contador para solicitudes con error
    }
  2. Bloque de procesamiento principal: Se ejecuta para cada línea del archivo de entrada

    {
        total++  ## Incrementar contador de solicitudes totales
        if ($6 >= 400) errors++  ## Contar respuestas con error (códigos de estado >= 400)
        ip_count[$3]++  ## Contar solicitudes por dirección IP (campo 3)
        resource_count[$5]++  ## Contar solicitudes por recurso (campo 5)
    }
  3. Bloque END: Se ejecuta después de procesar todas las líneas de entrada

    END {
        ## Imprimir estadísticas resumidas
        print "<p>Total requests: " total "</p>"
        print "<p>Error rate: " (errors/total) * 100 "%</p>"
    
        ## Procesar e imprimir las 5 direcciones IP principales
        #...
    
        ## Procesar e imprimir los 5 recursos solicitados principales
        #...
    
        print "</body></html>"  ## Finalizar estructura HTML
    }

Examinemos la lógica de clasificación para las IP principales (la sección de recursos funciona de la misma manera):

## Copiar los recuentos a una nueva matriz para la clasificación
for (ip in ip_count) {
    top_ips[ip] = ip_count[ip]
}

## Clasificar la matriz por valor en orden descendente
n = asort(top_ips, sorted_ips, "@val_num_desc")

## Imprimir las 5 entradas principales
for (i = 1; i <= 5 && i <= n; i++) {
    ## Encontrar la IP original que coincide con este recuento
    for (ip in ip_count) {
        if (ip_count[ip] == sorted_ips[i]) {
            print "<li>" ip ": " ip_count[ip] " requests</li>"
            break
        }
    }
}

En este script:

  • La función asort() clasifica la matriz
  • "@val_num_desc" es un argumento especial que le indica que clasifique numéricamente por valor en orden descendente
  • Los bucles anidados encuentran e imprimen las 5 entradas principales

Ahora, ejecutemos nuestro script AWK para generar el informe:

awk -f log_report.awk server_logs.txt > log_report.html

La opción -f le dice a AWK que lea el script del archivo especificado:

  • -f log_report.awk - Lee el script AWK del archivo log_report.awk
  • server_logs.txt - Procesa este archivo utilizando el script
  • > log_report.html - Redirige la salida al archivo log_report.html

Puedes ver el contenido del informe utilizando el comando cat:

cat log_report.html

Este informe proporciona un resumen de las solicitudes totales, la tasa de error, las 5 direcciones IP principales y los 5 recursos solicitados principales. En un escenario del mundo real, podrías abrir este archivo HTML en un navegador web para verlo en formato.

El enfoque que hemos utilizado en este script demuestra cómo se puede utilizar AWK para tareas de análisis de datos más complejas. Puedes extender este script para incluir estadísticas adicionales o diferentes visualizaciones según tus necesidades específicas.

Resumen

¡Felicidades! Has completado este laboratorio sobre el uso del comando AWK para el análisis de registros. Repasemos lo que has aprendido:

  1. Uso básico de AWK: Imprimir campos específicos de un archivo de texto estructurado.
  2. Filtrado de datos: Utilizar condiciones en AWK para seleccionar entradas de registro específicas.
  3. Conteo y resumen: Utilizar AWK para generar estadísticas a partir de datos de registro.
  4. Creación de informes: Escribir scripts de AWK más complejos para generar informes formateados.

Estas habilidades serán invaluable para analizar archivos de registro, procesar datos y generar informes en tu futuro trabajo como administrador de sistemas o analista de datos.

Aquí hay algunos parámetros y características adicionales de AWK que no cubrimos en este laboratorio:

  • -F: Especifica un separador de campos distinto del espacio en blanco.
  • -v: Asigna un valor a una variable.
  • NR: Una variable integrada que representa el número de registro actual.
  • NF: Una variable integrada que representa el número de campos en el registro actual.
  • Bloques BEGIN y END: Patrones especiales para la inicialización y finalización.
  • Funciones integradas: Funciones matemáticas, funciones de cadena y más.

Recuerda, la práctica es la clave para dominar AWK. Intenta modificar los comandos y scripts de este laboratorio para analizar diferentes aspectos del archivo de registro o para procesar otros tipos de datos de texto estructurado.

Recursos