Introducción a AWK
AWK es una herramienta poderosa para el procesamiento y análisis de archivos de texto. Fue diseñada para manipular datos estructurados, como archivos de registro o tablas. AWK procesa automáticamente el texto de entrada, dividiendo cada línea en campos y realizando operaciones sobre ellos.
La herramienta AWK se encarga automáticamente de muchas tareas, como la lectura de cada línea de entrada, la división de campos, la gestión de memoria y la inicialización de variables. En AWK, no es necesario declarar los tipos de datos de las variables, ya que el lenguaje incorpora tipos de cadena y numéricos.
Sintaxis básica
La sintaxis básica de AWK es:
awk [opciones] 'script' var=valor archivo(s)
o
awk [opciones] -f archivo_script var=valor archivo(s)
Ejemplo práctico
Supongamos que queremos encontrar todos los usuarios en el sistema que utilizan el shell bash en el archivo /etc/passwd:
awk -F':' '$7 == "/bin/bash"{print "Usuarios con bash shell: ",$1}' /etc/passwd
Este comando AWK realiza las siguientes acciones:
-F':': Utiliza el carácter de dos puntos como separador de campos.$7 == "/bin/bash": Filtra las líneas donde el séptimo campo es igual a "/bin/bash".{print "Usuarios con bash shell: ",$1}: Imprime el primer campo (nombre de usuario) junto con un mensaje descriptivo./etc/passwd: Es el archivo de entrada que se procesará.
Si el archivo /etc/passwd contiene:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
usuario_prueba:x:1000:1000:usuario_prueba:/home/usuario_prueba:/bin/bash
El resultado será:
Usuarios con bash shell: root
Usuarios con bash shell: usuario_prueba
Nota importante: Si la acción es print $1 $5, los campos se concatenarán porque el espacio en blanco es el carácter de concatenación en AWK. Por ejemplo, nombre = "abc" "bcd" es equivalente a nombre="abcbcd".
Opciones y parámetros
AWK ofrece numerosas opciones para personalizar su comportamiento:
-Fo--field-separator: Especifica el separador de campos. Por defecto utiliza espacios o tabuladores.-vo--assign: Define una variable y le asigna un valor.-fo--file: Especifica un archivo de script AWK.-Wo--word-regexp: Durante la coincidencia de patrones, solo coincide con palabras completas, no con fragmentos.-io--ignore-case: Ignora mayúsculas y minúsculas durante la coincidencia.-ho--help: Muestra información de ayuda sobre AWK.-Wlint: Habilita el modo de advertencia para detectar problemas potenciales en los scripts AWK.-Wposix: Habilita el modo de compatibilidad POSIX.-Wsource: Muestra el código fuente del script AWK.
Flujo de trabajo
El procesamiento de AWK se divide en tres fases principales:
- Bloque BEGIN: Código que se ejecuta antes de procesar el archivo de entrada.
- Bloque principal: Código que se ejecuta para cada línea del archivo de entrada.
- Bloque END: Código que se ejecuta después de procesar todo el archivo.
La sintaxis general es:
awk 'BEGIN{acciones} patrón{acciones} END{acciones}'
El flujo de trabajo es el siguiente:
- Se ejecuta el bloque BEGIN.
- Se inicia el porcesamiento del cuerpo del script.
- Se leen los registros (líneas) separados por saltos de línea.
- Cada registro se divide en campos según el separador especificado.
$0representa el registro completo (línea),$1el primer campo,$nel n-ésimo campo. - Para cada línea, se ejecuta el código del bloque si el patrón coincide.
- El proceso se repite para todas las líneas hasta el final del archivo.
- Finalmente, se ejecuta el bloque END para mostrar resultados finales o realizar tareas de limpieza.
Patrones de procesamiento
/patrón/{acciones}: Las acciones se ejecutan solo para las líneas que coinciden con el patrón.expresión1,expresión2{acciones}: Define un rango desde la línea que cumple expresión1 hasta la que cumple expresión2.
Formato de salida: print y printf
AWK ofrece dos comandos para mostrar resultados:
- print: Realiza una salida simple pero no permite formatear el resultado.
- printf: Permite un control detallado del formato de salida.
Diferencias entre print y printf
printfrequiere especificar un formato de salida.- El formato determina cómo se mostrarán cada uno de los elementos siguientes.
printfno añade automáticamente un salto de línea; debe especificarse con\n.printañade un salto de línea automáticamente al final.
Ejemplos de uso
Supongamos que tenemos un archivo de prueba llamado datos.txt con el siguiente contenido:
valor1 valor2 valor3 valor4 valor5
valor6 valor7 valor8 valor9 valor10
valor11 valor12 valor13 valor14 valor15
Podemos usar AWK para formatear la salida:
# Mostrar toda la línea sin formato
awk '{printf $0}' datos.txt
# Mostrar cada línea en una nueva línea
awk '{printf "%s\n", $0}' datos.txt
# Formatear la salida con etiquetas
awk '{printf "Primer campo: %s Segundo campo: %s Tercer campo: %s\n", $1, $2, $3}' datos.txt
Separadores de campo
AWK permite especificar separadores de campo de diversas formas:
-F " ": Por defecto, comprime todos los espacios en blanco iniciales, incluyendo tabuladores y espacios.-F " :": Cuando un espacio va seguido de dos puntos, se usa como separador. Comprime espacios eniciales pero no tabuladores.-F " ": Representa un solo espacio sin comprimir ningún espacio en blanco.-F "|": Especifica la barra vertical como separador.-F ",[ \t]|[ \t]+": Comas seguidas de cero o más espacios, o solo uno o más espacios, se usan como separadores.
Variables integradas
AWK proporciona varias variables integradas:
ARGV: Array de parámetros de línea de comandos, indexados desde 0 hasta ARGC-1.ARGC: Número de elementos en el array ARGV.FILENAME: Nombre del archivo actualmente en procesamiento.FNR: Número de registro en el archivo actual (file record number).NR: Número total de registros procesados. No se reinicia al procesar múltiples archivos.NF: Número total de campos en el registro actual (field number).FS: Separador de campos de entrada. Por defecto es espacio en blanco.OFS: Separador de campos de salida. Por defecto es espacio en blanco.RS: Separador de registros de entrada. Por defecto es "\n".ORS: Separador de registros de salida. Por defecto es "\n".OFMT: Formato para convertir números a cadenas enprintf. Por defecto es "%.6g".RLENGTH: Longitud de la cadena coincidente con la funciónmatch.RSTART: Posición inicial de la cadena coincidente con la funciónmatch.SUBSEP: Separador de subíndices. Por defecto es "\034".
Funciones integradas
Funicones matemáticas
cos(x): Devuelve el coseno de x.sin(x): Devuelve el seno de x.sqrt(x): Devuelve la raíz cuadrada de x.rand(): Devuelve un número aleatorio r, donde 0 ≤ r < 1.srand(x): Establece la semilla pararand()como x. La misma semilla produce los mismos resultados.int(x): Devuelve la parte entera de x.
Funciones de cadena
index(str1, str2): Devuelve la posición de la primera aparición de str2 en str1. Si no se encuentra, devuelve 0.length(str1): Devuelve la longitud de str1. Si no se especifica str1, calcula la longitud de "$0".substr(str1, p): Devuelve el sufijo de str1 comenzando en la posición p.substr(str1, p, n): Devuelve un substring de str1 comenzando en la posición p con longitud n.match(str1, regexp): Si regexp coincide con str1, devuelve la posición inicial. Establece RSTART y RLENGTH.split(str1, array, sep): Divide str1 usando el separador sep y almacena los resultados en array. Devuelve el número de elementos.sprintf(fmt, expr): Devuelve una cadena formateada según fmt a partir de expr.sub(regexp, rep, str2): Reemplaza la primera coincidencia de regexp en str2 con rep. Devuelve 1 si tuvo éxito.gsub(regexp, rep, str2): Reemplaza todas las coincidencias de regexp en str2 con rep. Devuelve el número de reemplazos.toupper(str): Convierte str a mayúsculas.tolower(str): Convierte str a minúsculas.
Variables personalizadas
Es posible definir variables propias en AWK:
awk -v variable="valor" 'NR==1{printf "%d %s\n", variable, $0}' archivo.txt
Este ejemplo asigna el valor "valor" a la variable "variable" y la utiliza en el script.
Funciones personalizadas
AWK permite definir funciones propias:
function nombre(lista-parámetros) {
declaraciones
}
Las funciones personalizadas permiten modularizar el código y reutilizar lógica común.
Estructuras de control
AWK soporte estructuras de control estándar:
Condicionales
if (expresión) declaraciones
if (expresión) declaraciones else declaraciones
Bucles
while (expresión) declaraciones
for (expresión; expresión; expresión) declaraciones
for (expresión in array) declaraciones
do declaraciones while (expresión)
Control de flujo
break: Sale del bucle actual.continue: Pasa a la siguiente iteración del bucle.next: Lee la siguiente línea y reinicia la ejecución del script desde el principio.exit código: Termina la ejecución e ingresa al bloque END. Si ya está en END, sale directamente.
Ejemplos de estructuras
# Condicional con patrón
/patrón/{if (condición){comando1; comando2;}else {comando3; comando4}}
# Condicional con bloque
/patrón/{
if (condición){
comando1
comando2
}
else
comando3
}
# Bucle while
/patrón/{
comando1
while (condición){
comando2
comando3
}
}
# Bucle do-while
/patrón/{
do{
comando1
comando2
} while (condición)
}
# Bucle for
/patrón/{
for (i=1; i<=10; i++){
comando1
comando2
}
}