Este artículo explora las capacidades de awk, que son más fáciles de usar ahora que sabes cómo estructurar tu comando en un script ejecutable.
Operadores lógicos y condicionales
Puedes utilizar los operadores lógicos y (escrito &&) y o (escrito ||) para añadir especificidad a tus condicionales.
Por ejemplo, para seleccionar e imprimir sólo los registros con la cadena «púrpura» en la segunda columna y una cantidad inferior a cinco en la tercera columna:
$2 == "purple" && $3 < 5 {print $1}
Si un registro tiene «púrpura» en la columna dos pero un valor mayor o igual a 5 en la columna tres, entonces no se selecciona. Del mismo modo, si un registro coincide con el requisito de la columna tres pero carece de «púrpura» en la columna dos, tampoco se selecciona.
Supongamos que desea seleccionar todos los registros de su archivo en los que el importe es mayor o igual a ocho e imprimir un registro coincidente con dos asteriscos (**). También quiere marcar cada registro con un valor entre cinco (inclusive) y ocho con un solo asterisco (*). Hay varias maneras de hacer esto, y una de ellas es utilizar el comando next para indicar a awk que después de realizar una acción, debe dejar de escanear y pasar al siguiente registro.
Aquí tienes un ejemplo:
NR == 1 {
print $0;
next;
}
$3 >= 8 {
printf "%s\t%s\n", $0, "**";
next;
}
$3 >= 5 {
printf "%s\t%s\n", $0, "*";
next;
}
$3 < 5 {
print $0;
}
Comando BEGIN
El comando BEGIN te permite imprimir y establecer variables antes de que awk comience a escanear un archivo de texto. Por ejemplo, puedes establecer los separadores de campos de entrada y salida dentro de tu script awk definiéndolos en una sentencia BEGIN. Este ejemplo adapta el sencillo script del artículo anterior para un archivo con campos delimitados por comas en lugar de espacios en blanco:
Comando END
El comando END, al igual que BEGIN, te permite realizar acciones en awk después de que éste complete su escaneo a través del archivo de texto que estás procesando. Si quieres imprimir resultados acumulados de algún valor en todos los registros, puedes hacerlo sólo después de que todos los registros hayan sido escaneados y procesados.
Los comandos BEGIN y END se ejecutan sólo una vez cada uno. Todas las reglas entre ellos se ejecutan cero o más veces en cada registro. En otras palabras, la mayor parte de su script awk es un bucle que se ejecuta en cada nueva línea del archivo de texto que está procesando, con la excepción de las reglas BEGIN y END, que se ejecutan antes y después del bucle.
Aquí hay un ejemplo que no sería posible sin el comando END. Este script acepta valores de la salida del comando Unix df e incrementa dos variables personalizadas (used y available) con cada nuevo registro.
$1 != "tempfs" {
used += $3;
available += $4;
}
END {
printf "%d GiB used\n%d GiB available\n", used/2^20, available/2^20;
}
Guarda el script como total.awk y pruébalo:
df -l | awk -f total.awk
Las variables used y available actúan como las variables en muchos otros lenguajes de programación. Las creas arbitrariamente y sin declarar su tipo, y les añades valores a voluntad. Al final del bucle, el script suma los registros en las respectivas columnas e imprime los totales.
Matemáticas
Como probablemente puedas deducir de todos los operadores lógicos y cálculos casuales hasta ahora, awk hace matemáticas de forma bastante natural. Esto podría ser una calculadora muy útil para tu terminal. En lugar de luchar para recordar la sintaxis bastante inusual de bc, puedes simplemente usar awk junto con su función especial BEGIN para evitar el requisito de un argumento de archivo:
$ awk 'BEGIN { print 2*21 }'
42
$ awk 'BEGIN {print 8*log(4) }'
11.0904
Es cierto que eso sigue siendo un montón de escritura para matemáticas simples (y no tan simples), pero no te costaría mucho esfuerzo escribir un frontend, lo cual es un ejercicio que puedes explorar.
Este artículo es una adaptación de un episodio de Hacker Public Radio, un podcast de tecnología comunitaria.