浅析awk里的数组

awk绝对是文本处理中的神器,它本身也是一门编程语言,还有许多功能本人没有使用到。这篇文章就单单针对awk里的数组来进行讨论,如何利用数组来帮助完成文本分析。

 

有这么一组数据:

 

abcd,91#31#2012-12-31 11:24:00
case_a,136#19#2012-12-31 11:24:00
case_a,136#23#2012-12-31 11:24:00
test_b,1000#22#2012-12-31 11:24:00
case_a,136#23#2012-12-31 11:24:00
group,83#38#2012-12-31 11:25:00
case_a,289#4#2012-12-31 11:25:00
case_a,289#15#2012-12-31 11:25:00
case_a,289#4#2012-12-31 11:25:00

 

 

以这行数据为例 “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]这种情况下,利用一维数组的遍历方法,得出来值如下格式:

i="a#b", arr[i]="value" 

然后再利用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)

 

得到的结果如下:

 

012-12-31 11:24:00 abcd,91 31
2012-12-31 11:24:00 case_a,136 65
2012-12-31 11:24:00 test_b,1000 22
2012-12-31 11:25:00 case_a,289 23
2012-12-31 11:25:00 group,83 38

 结果完全符合预期。

 

多维数组:

        以此类推,在需要用到三维数组、四维数组或以上的情况下,我们完全可以按照构造二维数组的方式来构造其他的多维数组,只需要多次利用split函数即可。

        但是具体对性能的影响就需要逐一去测试了。顺便推荐一个time命令。

 

---- EOF 2012/12/31-----

---- nigelzeng ----

你可能感兴趣的:(二维数组,array,数组,awk)