Is it a fake website?

09 enero 2008

awk - Mes de las herramientas unix; semana 1

Introducción
En este mes de las herramientas unix pretendo concentrar gran información práctica. Para saber más sobre las herramientas con las que practicaremos podreis consultar sus man pages.

Tabla de contenidos

  • Qué es awk?
  • Uso básico de awk
  • Registros y campos
  • Selección de campo
  • Patrones y funciones
  • Patrones mágicos; Begin, End
  • Ejemplo de expresiones de patrones
  • Variables
  • Arrays
  • Concatencación de cadenas
  • Ejemplo: Sumando el total del valor de un campo de un fichero de log
  • Ejemplo: ¿Cuantos archivos de cada tipo tiene abiertos mi usuario?
  • Ejemplo: Muestra archivos que no esten vacios
  • Ejemplo: Muestra las entradas del log comprendidas entre el 10 y el 20 de diciembre (incl):



  • ¿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)'


    NOTA: Perdonad la presentación, se que quedaría infinitamente mejor con estilos definidos y todo ese tipo de formateos, pero me centro en el contenido, no en la apariencia ;)

    4 comentarios:

    avilella dijo...

    muy bueno! queremos mas!! :-)

    Anónimo dijo...

    La verdad es que awk me ha sacado de bastantes apuros, gracias por ayudarnos a sacarle un mayor partido.

    Saludos!

    Emilio dijo...

    De nada!, espero que os subscribais al feed RSS si es que no estais ya subscritos. Va a haber mucho más contenido de este estilo.

    Saludos.

    Anónimo dijo...

    Excelente, simplemente hacia tiempo estaba buscando un tutorial asi... y no lo habia encontrado, simple pero poderoso :D