awk绝对是文本处理中的神器,它本身也是一门编程语言,还有许多功能本人没有使用到。这篇文章就单单针对awk里的数组来进行讨论,如何利用数组来帮助完成文本分析。
有这么一组数据:
以这行数据为例 “abcd,91#31#2012-12-31 11:24:00”,稍微解释下每列的意思:
第一列,abcd: 访问的URI
第二列,91: URI参数的值
第三列,31: 访问次数
第四列,显而易见,时间戳。
现在想要完成任务是根据时间戳来对URI进行访问次数的统计,最后的结果需要具有这样的格式:
时间戳 | URI和参数 | 访问次数 |
2012-12-31 11:24:00 | case_a,289 | 23 |
一维数组:
awk的一维数组是使用频率最高的数据结构,利用一维数组我们可以用某一列作为下标,把对应的值存入数组中。一维数组的用法简单明了:
awk '{arr[$2]+=$3} END{ for(i in arr) print i,arr[i] }'
用第二列做下标,对第三列求和。但是这样就不满足前面对结果的要求了,URI和参数无法体现出来。
也许你跟我想的一样,awk是否也有高级语言里的二维数组(多维数组)。
二维数组:
查阅了相关资料,awk里没有原生的二维数组支持,但是我们可以利用一维数组来构造二维数组,一维数组的表示arr[a],那么根据awk的性质,我们可以用arr[a#b]来表示二维数组(注意,awk不支持arr[a][b]之类的写法)。
也许你会有疑问,如何取出所有二维数组的值,在arr[a#b]这种情况下,利用一维数组的遍历方法,得出来值如下格式:
然后再利用awk的split内建函数来对i进行分割,得到一个新的一维数组,再进行一次遍历就可以达成前文的设想。直接上代码:
awk -F'#' '{sp="#";arr[$3sp$1]+=$2} END{ for(i in arr) { split(i,arr2,sp);print arr2[1],arr2[2],arr[i]} }' test.log |sort
稍作解释:
-F —— 设置awk的默认分隔符为"#"
sp=“#”——为下标分割符,split函数里也会用到。
split(i,arr2,sp) —— 以sp作为分隔符,对i进行分割,结果保存到arr2里。(详细信息请man awk)
得到的结果如下:
结果完全符合预期。
多维数组:
以此类推,在需要用到三维数组、四维数组或以上的情况下,我们完全可以按照构造二维数组的方式来构造其他的多维数组,只需要多次利用split函数即可。
但是具体对性能的影响就需要逐一去测试了。顺便推荐一个time命令。
---- EOF 2012/12/31-----
---- nigelzeng ----