awk中的’数组’

awk中的’数组‘是一种关联数组,又称作maps字典,他的索引不需要连续, 可以使用字符串、数字做为索引, 此外,不需要事先声明数组的大小 – 数组可以在运行时扩展/收缩。

语法:

  • 赋值:
array_name[index] = value
  • 删除:
delete array_name[index] 
  • 多维数组(使用字符串模拟)
array["0,0"] = 100
  • 遍历:
for (var in arrayname)
    actions

实例

统计汇总

数据:Iplogs.txt

180607 093423   123.12.23.122 133
180607 121234   125.25.45.221 153
190607 084849   202.178.23.4 44
190607 084859   164.78.22.64 12
200607 012312   202.188.3.2 13
210607 084849   202.178.23.4 34
210607 121435   202.178.23.4 32
210607 132423   202.188.3.2 167

total.awk:

 {
   Ip[$3]++;
 }
 END {
 for (var in Ip)
 print var, "access", Ip[var]," times"
 }

注意下END后的{需要和END在一行

输出:

$ awk -f total.awk Iplogs.txt
123.12.23.122 access 1  times
164.78.22.64 access 1  times
202.188.3.2 access 2  times
125.25.45.221 access 1  times
202.178.23.4 access 3  times

说明:
$3是一个IP地址, Ip做为数组的索引。
对于每一行,它会增加相应IP地址索引的值。
最后在END部分中,所有索引都将是唯一IP地址的列表,其对应的值是出现次数。

分组统计

数据:first.log.txt

0 child
0 parent
1 child
1 parent
2 parent
2 child
3 parent
3 child
4 parent
4 child
5 parent
5 child
6 parent
6 child
7 parent
7 child
8 parent
8 child
9 parent
9 child

The Linux Programming Interface中的例子:
fork_whos_on_first.count.awk

#!/usr/bin/awk -f
#
# fork_whos_on_first.count.awk
#
# Copyright, Michael Kerrisk, 2002
#
# Read (on stdin) the results of running the fork_whos_on_first.c
# program to assess the percentage iof cases in which parent or child
# was first to print a post-fork() message
#
BEGIN {
    last = -1;
}

{
    # match pairs of lines by field 1 (loop counter)

    if ($1 != last) {
    cat[$2]++;
    tot++;
    }
    last = $1;
}

    # Our input file may be long - periodically print a progress 
    # message with statistics so far
NR % 200000 == 0 { 
    print "Num children = ", NR / 2;
    for (k in cat) 
    printf "%-6s %6d %6.2f%%\n", k, cat[k], cat[k] / tot * 100;
}

END {
    print "All done";
    for (k in cat) 
    printf "%-6s %6d %6.2f%%\n", k, cat[k], cat[k] / tot * 100;
}

输出:


$ awk -f fork_whos_on_first.count.awk first.log.txt All done parent 8 80.00% child 2 20.00%

说明:
应用程序输出文本中通过$1进行分组,使用last存放上一个$1的值
通过if ($1 != last)判断是否是本组第一个出现的记录
$2是child或parent, 做为数组的索引。
对于每一组,它会增加相应IP地址索引的值。
NR记录行数,每200000输出一次.
最后在END部分中,可以通过数组显示child,parent键值,其对应的值是出现次数。

反转

reverse.awk:

{
a[i++] = $0
}
END {
for (j=i-1; j>=0;)
 print a[j--]
}

输出:

$ awk -f reverse.awk Iplogs.txt
210607 132423   202.188.3.2 167
210607 121435   202.178.23.4 32
210607 084849   202.178.23.4 34
200607 012312   202.188.3.2 13
190607 084859   164.78.22.64 12
190607 084849   202.178.23.4 44
180607 121234   125.25.45.221 153
180607 093423   123.12.23.122 133

说明:
它首先记录数组’a’中的所有行。
END块循环遍历数组’a’中的元素,并以反序打印。

也可以使用一下方法:

BEGIN{s=""} {s=$0"\n"s;} END{printf("%s",s);}

去重

数据:data.txt

foo
bar
foo
baz
bar

removedup.awk

!($0 in a) { a[$0]; print }

输出:

$ awk -f removedup.awk data.txt
foo
bar
baz

说明:
$0表示整行, awk从文件data.txt读取每一行,并使用“in”运算符检查当前行是否存在于数组a中。
如果它不存在,则存储并打印当前行。

选择最大值

max.awk:

{
date[$1]++;
}
END{
for (count in date)
{
    if ( max < date[count] ) {
        max = date[count];
        maxdate = count;
    }

}
print "Maximum access is on", maxdate;
}

输出:

$awk -f max.awk Iplogs.txt
Maximum access is on 210607

说明:
定义变量max,遍历数组获取最大值

多维数组矩阵反转

数据:vector.data

1 2 3 4 5 6
2 3 4 5 6 1
3 4 5 6 1 2
4 5 6 1 2 3

rotate.awk :

{ if (max_nf < NF)
      max_nf = NF
 max_nr = NR
 for (x = 1; x <= NF; x++)
    vector[x, NR] = $x
}
END {
  for (x = 1; x <= max_nf; x++) {
     for (y = max_nr; y >= 1; --y)
        printf ("%s ", vector[x, y])
   printf ("\n")
   }
}

输出:

$ awk -f rotate.awk vector.data
4 3 2 1
5 4 3 2
6 5 4 3
1 6 5 4
2 1 6 5
3 2 1 6

参考&引用

Arrays in awk
AWK Arrays Explained with 5 Practical Examples

Be First to Comment

发表回复