You are on page 1of 10

AWK

Introducción

El nombre awk proviene de las iniciales de sus desarrolladores : Alfred V. Aho, Brian W.
Kerningan y Peter J. Weinberger, de los Laboratorios Bell de AT&T. Inicialmente se
desarrolló para escribir programas muy cortos, pero las características de este atrajo a los
usuarios de tal modo, que lo impulsó más allá de la idea original de los autores. En 1985
apareció una nueva versión llamada nawk, en la que se implementan características nuevas
como son:

• Funciones de usuario.
• Expresiones regulares dinámicas con sustitución de texto.
• Mayor número de funciones intrínsecas y variables.
• Nuevos operadores y estamentos.
• Entrada de múltiples archivos.
• Acceso a argumentos en la línea de comandos.
• Mejora de los mensajes de error.

awk es un lenguaje de búsqueda y procesamiento de patrones. Esto quiere decir que awk es
capaz de buscar un patrón dentro de un archivo (al igual que grep) y tratarlo según unas
operaciones determinadas. Con awk se pueden desarrollar auténticos programas.

Según esto awk es capaz de procesar un archivo con datos organizados por columnas y
generar nuevas columnas con los valores resultantes de realizar ciertos cálculos u
operaciones.

A diferencia de comandos Unix como grep y sed, que filtran y procesan texto, awk
incorpora su propio lenguaje de programación, siendo capaz de ofrecer operaciones
aritméticas, relaciones lógicas y variables. Se pueden desarrollar programas con awk que
procesen la entrada estándar o un archivo, realizando tareas como tratar archivos de texto
como bases de datos. El lenguaje de programación awk incluye estamentos como for, while
e if-else, así como un conjunto de funciones y variables incorporadas.

Sintaxis

La sintaxis de awk es:

awk [-f archivo_programa] [-Fc] ['programa'] [variable=valor ...] [archivo]

donde:

archivo_programa : especifica el archivo fuente del programa a aplicar a


archivo.
c : especifica el carácter delimitador de campos. Por defecto se considera el
espacio en blanco.
programa : especifica el conjunto de patrones e instrucciones a ejecutar con
archivo. La diferencia con archivo_programa, es que en este caso hay que
especificar los patrones e instrucciones en la línea de comandos. Para evitar
interferencias con la shell deben ir encerradas entre comillas simples (').
variable=valor : se utiliza para establecer los valores que tomarán las
variables que utilice el programa.
archivo : archivo que será procesado por awk. Si se especifica "-" se
interpretará como la entrada estándar.

Campos y Variables

Una línea de entrada se divide en campos separados por espacios, y cada campo se
denomina como $1, $2, etc. $0 indica la línea entera. Estas variables se pueden manipular
(sumar, cambiar, etc.) como cualquier otra varible, por ejemplo:

awk '{ $1 = $2 + $3; print $0 }' archivo

Sumará los campos 2 y 3 en el campo 1, e imprimirá el nuevo registro (la línea completa).

Se pueden referir a los campos con expresiones numéricas como $i, $(n+1), $(NF*3/NR),
etc. Si la expresión resultante no es un entera, se truncará la parte decimal. El tratamiento
de un campo como texto o numérico dependerá del contexto, awk resuelve las posibles
ambigüedades tratando los campos como texto (por ejemplo cuando se compara un texto
con un número), por ejemplo:

x=10 Asigna a x el valor numérico 10


x="Hola" Asigna a x la cadena Hola
Asigna a x el valor 4, como si se hubiera escrito x=2+2, debido a que el
x="2"+"2"
contexto demanda un valor numérico.

En los programas de awk no es necesario declarar las variables (indicar el tipo de variable
de que se trata), se realizará automáticamente en función del contexto. Por defecto se
inicializan a la cadena nula o valor numérico 0, por lo que no es necesario inicializarlas.

Existen unas variables predefinidas, que pueden ser utilizadas dentro del programa:

• FS : Separador del campo de entrada. Se puede especificar con la opción -Fc en la


línea de comandos
• RS : Separador de registro de entrada
• OFS : Separador del campo de salida.
• ORS : Separador de registro de salida
• NF : Número de campos en el registro actual
• NR : Número de registros procesados hasta el momento. Al final del programa se
podrá conocer el número e registros tratados.
• RSTART : Posición de la cadena en la que se verifica el patrón utilizado,
comenzando desde 1. Es equivalente al valor retornado por la función match.
• RLENGTH : Longitud de la cadena en la que se verifica el patrón utilizado.
• SUBSEP : Separador de cadenas en arrays multidimensionales. El valor por defecto
es " 34".

Los valores de las variables relativas a separadores se pueden modificar en cualquier


momento, asignándole el valor de cualquier carácter. Por defecto, los separadores de
campos son espacios, y los de registros el carácter nueva línea.

Formato de los estamentos

La estructura general de los estamentos o conjuntos patrón-acción es:

Patrón { acción }

Interpretación:

• Para cada línea que verifique lo especificado en el patrón, se ejecutará la acción


indicada.
• La acción siempre va encerrada entre llaves.
• Se pueden especificar varias acciones, separándolas por ";" o por el carácter nueva
línea.

Si no se especifica la acción, se mostrarán por pantalla aquellas líneas que contengan el


patrón. La acción está formada por estamentos (if, for, print, sprintf, next), los cuales deben
finalizar en ";", Nueva Línea o llaves. Dentro de las acciones se pueden realizar
operaciones matemáticas, de concatenación, etc. Las variables utilizadas pueden ser
escalares, campos o tablas, y son inicializadas a la cadena nula.

Los patrones deben ir rodeados por caracteres "/", y puede contener dos patrones separados
por una coma, en cuyo caso la acción se realizará para aquellas líneas comprendidas entre
la primera aparición del primer patrón y la siguiente aparición del segundo patrón. Si se
utiliza el símbolo "~", indicará que el patrón de la derecha está contenido en el campo de la
izquierda, y si se utiliza "!~", indicará que no está contenido.

Existen dos etiquetas opcionales, con un significado especial, que hacen que un programa
awk tenga una estructura como la siguiente:

BEGIN { acción }
Patrón { acción }
END { acción }

La acción indicada en la etiqueta BEGIN se ejecutará antes de leer cualquier entrada,


mientras que la acción asociada a la etiqueta END se ejecutará una vez tratadas todas las
entradas. La etiqueta END se puede utilizar para imprimir resultados totales, o cálculos
realizados con todos los registros leídos.

Cuando el conjunto patrón-acción se introduce desde la línea de comandos, se recomienda


que vaya encerrado entre comillas simples, para protegerlo de la shell. Por ejemplo:

Desde un archivo Desde la shell de Unix


length > 60 awk 'length > 60'

A continuación se muestran los diferentes tipos de acciones y estamentos.

if (expresión) estamento [else estamento]


while (expresión) estamento
for (inicialización ; final ; incremento)
estamento
for (var in array) estamento
do estamento while (expresión)
break
continue
[ [estamento] }
expresión por ejemplo una asignacion var=valor
print [lista de expresiones] [ > expresión]
printf formato[, lista de expresiones] [ >
expresión]
return [expresión]
salta los elementos restantes de la línea de
next
entrada
delete array [expresión] Borra un elemento array
Finaliza la ejecución del programa,
exit [expresión]
devolviendo el valor indicado en expresión.

Operaciones

Un programa awk puede hacer operaciones en coma flotante, utilizando los siguientes
operadores:

+, -, *, / Adición, sustración, multiplicación y división


% Operador módulo o resto.
++, -- Operador de incremente y decremento
+=, -=, *=, /=, %= Asinación al estilo C (x += 1 equivale a x = x + 1)

Funciones Incorporadas
Las siguientes funciones se pueden utilizar para la realización de operaciones aritméticas y
con cadenas de caracteres.

Función Descripción
length(x) Devuelve la longitud del argumento
sqrt(x) Devuelve la raíz cuadrada del argumento
log(x) Devuelve el logaritmo en neperiano del argumento (en base e)
exp(x) Devuelve el valor de e elevado al argumento
int(x) Devuelve la parte entera del argumento
cos(x) Devuelve el coseno del argumento
sin(x) Devuelve el seno del argumento
atan(x) Devuelve el arcotangente del argumento
rand() Devuelve un número aleatorio comprendido entre 0 y 1
Devuelve la posición de s en donde ocurre r, comenzando desde 1. Si no
match(s,r)
existe devuelve 0.
Devuelve la subcadena de s que comienza en la posición m y finaliza en
substr(s,m,n)
la n.
Sustituye la primera ocurrencia de t por r en la cadena s. Si no se
sub(r,t,s)
especifica s se tomará todo el registro ($0).
gsub(r,t,s) Igual que sub, pero sustituyendo todas las ocurrencias.
Divide la cadena s en array[1],...,array[n]. Se devuelve el número de
split(s,array,sep) elementos. Si no se especifica el separador en sep se utilizará el valor de
FS. s puede ser una variable.
Devuelve la posición de la cadena s1 en donde se encuentra la cadena s2.
index(s1,s2)
En caso de no encontrarse se devuelve 0.
Devuelve la cadena resultante de imprimir los valores e1, e2, ... con el
sprintf(f,e1,e2,...)
formato especificado en f.
toupper(s) Devuelve la cadena s convertida a mayúsculas.
tolower(s) Devuelve la cadena s convertida a minúsculas.
Ejecuta el comando UNIX cmd especificado y retorna el estado de salida
system(cmd)
de este.
print e1, e2, ... Presenta en la salida los valores e1, e2, ...
Presenta en la salida los valores e1, e2, ... con el formato especificado
printf f, e1, e2, ...
por f (al estilo C: %s, %d, etc.).
close(f) Cierra el archivo o pipe abierto con print, printf o getline.
Lee el siguiente registro de la entrada y se lo asigna a X, si no se
getline X
especifica X se asignará a $0.

Funciones
Las funciones se pueden definir (en la posición de un estamentopatrón-acción) del siguiente
modo:

function Nombre_Función(p1, p2, p3) { ..., return x }

Los parámetros se pasan por valor si son escalares y por referencia si se pasa el nombre del
array. Los parámetros son locales, mientras que el resto de las variables son globales. Las
funciones pueden llamarse de forma recursiva.

Ejemplos

Ejemplos de patrones

/prueba/ Todas las líneas que contengan la cadena "prueba".


$2 ~ /prueba/ Todas las líneas cuyo segundo campo contenga la cadena "prueba".
$1 !~ /prueba/ Todas las líneas cuyo primer campo no contenga la cadena "prueba".
/start/ , /stop/ Imprime todas las líneas existentes entre los patrones start y stop.

Ejemplos de acciones

{ print $5 } Imprime el campo 5.


{ print $1 $3 } Imprime los campos 1 y 3 consecutivamente.
{ s=$2+$3 ; print s } Suma los campos 2 y 3 e imprime el resultado.
Suma de los campos 2 y 3, e imprime la línea original y
{tot=$2+$3; print $0, tot}
la suma.
Toma como separador de entrada la coma y/o los
BEGIN {FS = ",[ \t]*|[ \t]+" }
blancos y tabulaciones.
{ s += $1; print $2, $1 }
Suma el primer campo de todos los registros e imprime
END { print "La suma es ", s ,
los campos 2 y 1 (en ese orden).
"La media es ", s/NR
Al final imprime el total y la media.

Ejemplos

Muestra los archivos que contengan como propietario, nombre,


ls -l | awk '/txt/ { print
grupo, etc. la cadena txt. El símbolo "-" indica que el archivo es
&8 }' -
la entrada estándar.
Busca cadena en archivo y en una variable llamada cont
awk '/cadena/
(contador) va sumando los valores del campo 2 e imprimiendo
{ cont=cont+$2 ; print
dicho campo, un tabulador y el valor del contador. Al final de la
$2 "\t" cont }' cont=0
salida tendremos la suma total de los valores que ha tenido
archivo
cadena en el campo 2.
awk '$2>0 { print $1," ", Para cada línea de archivo, si el 2º campo es positivo, imprime
$2 }' archivo los dos primeros campos.
awk '$2>0 { printf "%s Idem que el caso anterior, suponiendo que el primer campo es
%d\n", $1, $2 }' archivo una cadena de caracteres.
awk '{gsub(" ","",$0); Elimina todos los espacios en blanco del archivo especificado y
print $0;}' archivo lo muestra en pantalla.

# El siguiente ejemplo suma las columnas 2, 3 y 4 de un archivo,


presentando el resultado al final.
cat archivo | awk '
BEGIN { campo1=0; campo2=0; campo3=0; }
{
campo1+=$2;
campo2+=$3;
campo3+=$4;
}
END { printf "campo1 = %d\t campo2 = %d\t campo3 = %d\n", campo1,
campo2, campo3; }'

# En el siguiente ejemplo se hace lo mismo que en el anterior pero para


las líneas que contengan
la palabra TOTAL en el primer campo.
cat archivo | awk 'BEGIN { campo1=0; campo2=0; campo3=0; } $1 ~ /TOTAL/ {
campo1+=$2;
campo2+=$3;
campo3+=$4;
}
END { printf "campo1 = %d\t campo2 = %d\t campo3 = %d\n", campo1,
campo2, campo3; }'

2. ¿Para qué sirve awk?


« Anterior | Inicio | Siguiente »
Como ya se ha indicado, esta utilidad permite procesar secuencialmente uno o varios
archivos, los cuales constituyen la información “entrante” para awk. El contenido de cada
una de las líneas de la entrada se compara con una o varias plantillas, en las que debe
especificarse un patrón de búsqueda. A cada patrón se le asocia una acción, que,
normalmente, procesa la información entrante y la envía a la salida estándar.
Por tanto, los usos típicos de awk se centran en la selección de registros de un archivo en
función de uno o varios criterios de búsqueda. Si solamente resultara relevante una parte
del registro seleccionado, también sería posible separarla e ignorar el resto.
La información "saliente" se puede transformar según las necesidades del usuario, por lo
que es posible crear informes con muy poco esfuerzo de programación.
La sintaxis es muy semejante a la del lenguaje C, con la particularidad de que, al ser awk un
intérprete, no es necesario pasar por procesos de compilación y linkedición. El rendimiento
de awk no es comparable al de un ejecutable, pero, dada la orientación al proceso
secuencial de archivos, esta circunstancia solamente es relevante en condiciones extremas.
Awk puede, además, leer y grabar simultáneamente otros archivos, además de la entrada y
salida estándar. Otras capacidades avanzadas quedan, por su mayor dificultad, fuera del
alcance de este artículo.
Conviene, finalmente, recalcar la circunstancia de que awk solamente procesa archivos de
texto. Para manejar los datos de una hoja Excel o de cualquier otro documento en formato
propietario es necesario exportar la información a algún formato de texto.

5. Primeros pasos con awk


« Anterior | Inicio | Siguiente »
Todo el proceso gira en torno a la comparación de todas las líneas del archivo, leídas una
por una en secuencia, con una o más plantillas. Cada plantilla contiene una expresión, y
lleva asociada una acción. La sintaxis es, en general, de la forma:

expresión { acción }

Si la evaluación de la expresión resulta positiva, se realiza la acción asociada. El resultado


de una expresión vacía se considera siempre positivo. Si la acción se omite, se asume que lo
que se desea es mostrar el registro en la salida estándar. Este proceso se reitera con cada
línea, hasta llegar al final del archivo.
En el siguiente ejemplo se pasa como único parámetro la plantilla entre comillas simples:

$ cat ejemplo.txt | awk '1'La bella y graciosa mozamarchóse a lavar la ropala frotó sobre
una piedray la colgó de un abedul. $ _

Esta plantilla contiene una expresión trivial (1), cuya evaluación resulta siempre positiva.
En ausencia de una acción asociada explícitamente, awk asume la acción por omisión, que
consiste en mostrar la línea completa en stdout. Se puede añadir una acción algo más
sofisticada entre llaves:

$ cat ejemplo.txt | awk '1 { print “línea” }'línealínealínealínea$ _


Como puede observarse, la acción print se realiza una vez por cada línea que se obtiene de
stdin. Para emplear más de una plantilla se emplea la construcción “expresión { acción }”
repetidas veces, como en el siguiente ejemplo:

$ cat ejemplo.txt | awk '1 { print “línea” } 1 { print


“recta” }'línearectalínearectalínearectalínearecta$ _

También es posible incorporar varias instrucciones en la misma acción, separadas por el


signo “punto y coma”:

$ cat ejemplo.txt | awk '1 { print “Yo uso”; print “Linux” }'Yo usoLinuxYo
usoLinuxYo usoLinuxYo usoLinux$ _

Para no confundir al lector, se omite deliberadamente la mención de la posibilidad de usar


expresiones regulares semejantes a las que usa "grep". Si el distinguido público lector
manifiesta un ferviente deseo de profundizar en el tema, el autor considerará seriamente la
posibilidad de ampliar la información al respecto.

9. Awk en acción
« Anterior | Inicio | Siguiente »
Para recapitular lo visto hasta ahora, se realizará a continuación algún proceso sencillo con
el archivo de ejemplo mostrado en párrafos anteriores. El archivo entrante contiene un
número teóricamente no determinado de registros, terminados por el carácter contenido en
RS. El proceso comienza leyendo el primer registro, aplicando a éste todas las plantillas
existentes con el valor de la variable NR igual a 1. Se reitera el proceso para cada registro,
incrementando en una unidad el valor de NR cada vez.

Cada registro está compuesto por NF campos, delimitados por las apariciones del carácter
FS en el mismo. El ordinal de cada campo se designa, como se indicó arriba, con $1, $2,
$3… y así hasta $NF.

Con campos, variables y operadores se puede escribir una plantilla algo más útil que las
anteriores:

$ awk '$5

“moza” { print “La linea”, NR, "contiene MOZA en el quinto campo”; }' ejemplo.txt
La línea 1 contiene MOZA en el quinto campo
$_
A medida que la lógica de las plantillas se complique, será de utilidad el parámetro –f
(minúscula) seguido del nombre del guión o script que contendrá las plantillas. Cuando las
plantillas se codifican dentro del script, no se usan las comillas simples para delimitarlas.
Un guión típico como el que se muestra (“proceso.awk” en el directorio actual) podría tener
el siguiente contenido:

$ cat proceso.awk { print "Procesando la línea", NR }


NF > 1 { print “La línea tiene más de una palabra” }
$1

“Linux” {print “La primera palabra es Linux”}


$_

La primera plantilla siempre se ejecuta por no tener expresión delante de las llaves. La
segunda solamente se activa para las líneas que tienen más de una palabra. La tercera es
aplicable si la línea comienza con la palabra “Linux”.

You might also like