lunes, enero 14, 2008

Mini manual (como) de awk

¿Qué es awk?
awk es una de las más útiles herramientas de filtrado que encontraras. Awk es un completo lenguaje de script, pero nos centraremos exclusivamente en su uso en la shell.

Uso básico de awk


awk [-F] [awk_script]


Registros y campos

Awk tiene dos conceptos de datos que vienen de la entrada de un archivo: registros y campos.
Un registro es generalmente una línea entera. El separador de registro por defecto es una nueva línea (RS). Pero se puede cambiar.

Un campo es generalmente una palabra entre espacios en blanco (tabulador o espacio). El separador de campo por defecto es un espacio (FS). También se puede cambiar en cualquier momento.



Selección de campo

A los campos se accede usando el "operador" $. Son válidos:

$1,$2,$3: (primer, segundo y tercer campos)
$NF: (el último campo, es una variable que contiene el número total de campos)
x=1; $(x+3): (equivale al cuarto campo, pero esto ya es liarla :P )

Ejemplo.
Muestra con la que trabajaremos


#tail -1 access.log
1199488503.117 239 127.0.0.1 TCP_REFRESH_UNMODIFIED/304 310 GET http://www.logadmin.net/ - NONE/- -



Ejemplo

#awk '{print $7}' access.log
http://www.logadmin.net/

Podemos combinar.
#awk '{print $7 " " $9}' access.log
http://www.logadmin.net/ DIRECT/72.14.207.121
Y formatear


#awk '{print $7 "\t" $9}' access.log
http://www.logadmin.net/ DIRECT/72.14.207.121


Si ejecutamos el mismo comando con un fichero diferente, pongamos /etc/passwd
no mostrara nada por 2 razones, ¿adivinais por que?
Arreglemoslo entonces.

#awk -F: '{print $1 " " $6}' /etc/passwd
logadmin /home/logadmin

Patrones y funciones
Las expresiones de awk vienen en dos formas; un patrón o una función. Nos centraremos en los patrones que es lo que más se usa.

Un patrón será algo como: [ expresión de la condición ] { [ expresión de la acción ] }
En pseudocódigo sería: if ( expresión de la condición ) { expresión de la acción }
Si no existiera ninguna acción, por defecto haría un 'print'. Si no hubiera condición, por defecto ejecutaría la acción para todos los campos.


Patrones mágicos: BEGIN Y END

BEGIN se usa para ejecutar cosas antes de que se parsee la primera expresión, y END obviamente hace las cosas después de que se haya ejecutado el último registro.


Ejemplo de expresiones de patrones


$1 ~ /foo/ { print $2 }
Imprime el segundo campo de todos los registros de aquellos donde el primer campo coincida con /foo/

$2 > 128
Imprime todos los registros donde el segundo campo se más grande que 128


Variables

Las variables tienen la misma sintáxis que en C, pero no tienes que declararlas.

$3 == "test" { x++ }; END { print x }
Registros totales donde $3 == "test"

{ $1 = ""; print }
Borrar el primer campo de cada registro, imprime el nuevo campo.

{ $3 = "Hola"; print }


Arrays

Los arrays son mágicos. Simplemente empieza usando una variable como un array, y se convertirá en array.
#awk '{ a[$1]++ } END { for (i in a) { print i, a[i] } }'


Concatenación de cadenas

Juntar cadenas es muy simple.

x = "log"; x = x"admin"; # x == "logadmin"


Ejemplo: Sumando el total del valor de un campo de un fichero de log.

Del fichero de log que habíamos elegido al principio, hacemos;

#awk 'BEGIN{total=0;} {total += $5;} END{print "el total es ", total}' access.log
el total es 28677417

Donde $5 es el quinto campo (bytes tranferidos) y obtenemos el total del tamaño transferido en ese log.


Ejemplo: ¿Cuantos archivos de cada tipo tiene abiertos mi usuario?

#lsof -u logadmin | sed 1d| awk '{a[$1]++} END { for (i in a) { print i, a[i] } }' | sort -nk2
gnome-pty 4
ssh-agent 4
awk 9
compiz 9
firefox 9
run-mozil 9
mapping-d 15
sed 21
sort 21
lsof 31
..


Ejemplo: Muestra archivos que no esten vacios.


# ls -l | awk '$5 > 0'


Ejemplo: Muestra las entradas del log comprendidas entre el 10 y el 20 de diciembre (incl).


# cat *.log | awk '$1 == "Dec" && ($2 >= 10 && $2 <= 20)'

No hay comentarios.: