用awk解决一个问题

工作上要处理一个问题,每天分析员会把全国路由节点近段使用DNSIP最多次数的数据生成到一个文件中,我需要把这些数据每天更新到redis集群中去。文件不算大,大约30万行每天,体积在20M左右。

因为环境问题考虑用bash编程,最开始考虑读每行然后插入。但是效率肯定不会好,于是尝试使用awk编程,写一个函数处理IP转INT,然后把函数转为系统函数

export -f function

然后在awk中调用

awk 'NF>1{system("ip2int "$1" "$2)}' $date > out

其中$!,$2都是IP,传到ip2redis函数中。它可以一次转两个IP。

这样效率很慢,我试了试,大约1小时。

 

然后就考虑用awk编程,直接在awk中使用

awk '\
 BEGIN{FS="[\t.]"}
 NF>7{ip=($1*(2^24))+($2*(2^16))+($3*(2^8))+$4;
 dns=($5*(2^24))+($6*(2^16))+($7*(2^8))+$8;
 print "*3\r\n$3\r\nSET\r\n$"length(ip)"\r\n"ip"\r\n$"length(dns)"\r\n"dns"\r\n"}

 \' $date > outs

首先使用\t和.作为分隔符,然后取前4个数组为第一个IP,5-8个为DNSIP,分别对其转整数,然后按照REDIS协议生成字符串以便导入。

这个脚本执行时,大约只需要5s。

顺道说句REDIS的批量导入:

cat outs | redis-cli --pipe  

这个命令不到不少坑,按照他们的格式操作了还是总报错误。最后发现了关键点,awk每输出一行都会在后面加个换行,这个是有问题的。

之前还考虑过用纯字符’\r\n’ ,后来发现不是关键所在。

解决办法是设置换行为””

BEGIN{FS="[\t.]";ORS=""}

关于redis protocol也值得说一下,在使用redis pipe的时候,是将批量的redis命令导入。但是需要先转换成redis协议支持的格式,如下:

*3\r\n #这个*后面表示要传送几个字段,这是是三段,SET key value
$3\r\n #这个$后面表示这个字段的字节数,SET是3
SET\r\n #这是第一个字段,其他命令也是这种格式
$3\r\n 
key\r\n 
$5\r\n 
value\r\n

← TCP/IP详解读书笔记  Python语法知识点 →