September 25, 2015

Qué es awk?

  • Un lenguaje de programación.

  • Optimizado para procesamiento de texto, capaza de realizar manipulaciones de cadenas de caracteres, y operaciones aritméticas.

  • Útil para hacer cálculos sencillos, de forma rápida.

  • Puede servir tambien como herramienta de pre-procesamiento de datos, para alimentar una herramienta de alto nivel, como una hoja de cálculo.

  • Para los ejemplos usaré: https://www.ecobici.df.gob.mx/sites/default/files/data/usages/2015-08.csv

Operaciones básicas

  • Puede servir como un head :
  awk 'NR < 10 {print $0}' 2015-08.csv 
## Genero_Usuario,Edad_Usuario,Bici,Ciclo_Estacion_Retiro,Fecha_Retiro,Hora_Retiro,Ciclo_Estacion_Arribo,Fecha_Arribo,Hora_Arribo
## F,28,0720,53,2015-08-01,00:00:06.610000,136,2015-08-01,00:23:25
## M,48,3999,70,2015-08-01,00:00:09.047000,163,2015-08-01,00:32:42.437000
## M,24,2586,157,2015-08-01,00:00:18.437000,153,2015-08-01,00:05:19
## M,41,3805,22,2015-08-01,00:01:04.347000,9,2015-08-01,00:12:32
## M,26,2613,46,2015-08-01,00:01:16.657000,80,2015-08-01,00:11:07.100000
## M,20,5001,60,2015-08-01,00:01:16.780000,182,2015-08-01,00:07:38
## M,33,0183,191,2015-08-01,00:01:16.890000,189,2015-08-01,00:02:58
## M,29,2312,180,2015-08-01,00:01:24.940000,261,2015-08-01,00:18:20
  • O como un wc:
  awk 'END{print FNR}' 2015-08.csv
## 805531

Operaciones básicas

  • Como un grep:
  awk -F, '(NR < 20 && $1=="F") {print $0}' 2015-08.csv
## F,28,0720,53,2015-08-01,00:00:06.610000,136,2015-08-01,00:23:25
## F,56,6172,118,2015-08-01,00:01:42.787000,115,2015-08-01,00:04:33.500000
## F,30,3254,63,2015-08-01,00:02:18.773000,446,2015-08-01,00:28:27
## F,22,4598,146,2015-08-01,00:02:21.113000,146,2015-08-01,00:11:09.217000
## F,29,5500,22,2015-08-01,00:02:41.520000,174,2015-08-01,00:21:42.620000
  • Incluso como un sed:
  awk 'NR < 5 {gsub("M","Macho",$0); gsub("F","Female",$0); print $0}' 2015-08.csv
## Genero_Usuario,Edad_Usuario,Bici,Ciclo_Estacion_Retiro,Femaleecha_Retiro,Hora_Retiro,Ciclo_Estacion_Arribo,Femaleecha_Arribo,Hora_Arribo
## Female,28,0720,53,2015-08-01,00:00:06.610000,136,2015-08-01,00:23:25
## Macho,48,3999,70,2015-08-01,00:00:09.047000,163,2015-08-01,00:32:42.437000
## Macho,24,2586,157,2015-08-01,00:00:18.437000,153,2015-08-01,00:05:19

Pero su verdadero poder aparece al agregar y operar sobre los datos

  • Calculando el promedio de una columna:
awk -F, '{if(NR == 1){ column=$2}; sum += $2; n++} END\
{print("Promedio de "column": "sum/n " años.")}'  2015-08.csv
## Promedio de Edad_Usuario: 34.1454 años.
  • O combinando varias:
awk -F, 'function timetosec(date,time)\
{m = split(date,days,"-");\
n = split(time,array,":");\
month_secs = (days[2]-8)*31*24*3600+days[3]*24*3600
seconds = month_secs+array[1]*3600 + array[2] * 60 + array[3];\
return seconds}\
NR >1 {sum_tiempo+=(timetosec($8,$9)-timetosec($5,$6)); k++} END\
{print "Tiempo promedio de recorrido: " sum_tiempo/k " segundos."}'  2015-08.csv
## Tiempo promedio de recorrido: 851.385 segundos.

Haciendo filtros

awk -F, 'function timetosec(date,time)\
{m = split(date,days,"-");\
n = split(time,array,":");\
month_secs = (days[2]-8)*31*24*3600+days[3]*24*3600
seconds = month_secs+array[1]*3600 + array[2] * 60 + array[3];\
return seconds}\
NR >1 {if ($1=="M") {sum_tiempo_m+=(timetosec($8,$9)-timetosec($5,$6)) ; km++;} \
else {sum_tiempo_f+=(timetosec($8,$9)-timetosec($5,$6)) ; kf++}} END\
{print "Tiempo promedio de recorrido (Hombres): " sum_tiempo_m/km " segundos.";\
print "Tiempo promedio de recorrido (Mujeres): " sum_tiempo_f/kf " segundos."}' 2015-08.csv
## Tiempo promedio de recorrido (Hombres): 818.563 segundos.
## Tiempo promedio de recorrido (Mujeres): 943.821 segundos.

Y por supuesto, como un mapper

awk -F, 'function timetosec(date,time)\
{m = split(date,days,"-");\
n = split(time,array,":");\
month_secs = (days[2]-8)*31*24*3600+days[3]*24*3600
seconds = month_secs+array[1]*3600 + array[2] * 60 + array[3];\
return seconds}\
NR < 10 { if (NR ==1) print $0",Tiempo_de_Recorrido"; else \
print $0","(timetosec($8,$9)-timetosec($5,$6))}' 2015-08.csv
## Genero_Usuario,Edad_Usuario,Bici,Ciclo_Estacion_Retiro,Fecha_Retiro,Hora_Retiro,Ciclo_Estacion_Arribo,Fecha_Arribo,Hora_Arribo,Tiempo_de_Recorrido
## F,28,0720,53,2015-08-01,00:00:06.610000,136,2015-08-01,00:23:25,1398.39
## M,48,3999,70,2015-08-01,00:00:09.047000,163,2015-08-01,00:32:42.437000,1953.39
## M,24,2586,157,2015-08-01,00:00:18.437000,153,2015-08-01,00:05:19,300.563
## M,41,3805,22,2015-08-01,00:01:04.347000,9,2015-08-01,00:12:32,687.653
## M,26,2613,46,2015-08-01,00:01:16.657000,80,2015-08-01,00:11:07.100000,590.443
## M,20,5001,60,2015-08-01,00:01:16.780000,182,2015-08-01,00:07:38,381.22
## M,33,0183,191,2015-08-01,00:01:16.890000,189,2015-08-01,00:02:58,101.11
## M,29,2312,180,2015-08-01,00:01:24.940000,261,2015-08-01,00:18:20,1015.06

Y salen marvillas combinándolo con otras herramientas:

  • Por ejemplo, haciendo un histograma de edades:
for i in `awk -F, '{print 10*int($2/10)}' 2015-08.csv|sort -u -n`; do \
awk -F, -v age=$i 'NR>1 && 10*int($2/10)==age {k++} END {print age","k}' 2015-08.csv; \
done
## 0,
## 10,10701
## 20,311187
## 30,283055
## 40,121435
## 50,60762
## 60,16276
## 70,2062
## 80,40
## 90,3
## 110,9
  • Comprobando que los millenials son el grupo que más usa la Ecobici.

Gracias

Espero que les sea de utilidad.