专业的linux技术站点
Controlled by you.

awk进阶用法- 数组/复合索引数组/遍历顺序指定

一、awk数组去除重复行

root@debian:~/awk# cat x.log
abc
def
ghi
abc
ghi
xyz

mnopq
abc
root@debian:~/awk# awk '{arr[$0]++}END{for(i in arr)print i}' x.log    ###由于用了for循环,遍历是无序的

def
mnopq
abc
ghi
xyz

如果想不打乱顺序按原样输出,则不能使用for

root@debian:~/awk# awk '!arr[$0]++{print $0}' x.log
abc
def
ghi
xyz

mnopq
root@debian:~/awk

分析:!arr[$0]++作为partten,只有第一次出现的值为空(为假),取反后则为真,执行main代码块

二、指定遍历顺序

awk数组为关联数组,默认情况下,for(idx in arr)遍历数组时顺序是不可预测的。
但gawk提供了PROCINFO["sorted_in"]来指定遍历的元素顺序。它可以设置为两种类型的值:
– 设置为用户自定义函数
– 设置为下面这些awk预定义好的值:

预定义值 说明
@unsorted 默认值,遍历时无序
@ind_str_asc 索引按字符串比较方式升序遍历
@ind_str_desc 索引按字符串比较方式降序遍历
@ind_num_asc 索引强制按照数值比较方式升序遍历,无法转换的字符串索引将当做数值0进行比较
@ind_num_desc 索引强制按照数值比较方式降序遍历,无法转换的字符串索引将当做数值0进行比较
@val_type_asc 按值升序比较,数值类型>字符串类型>数组类型,即num>str>arr
@val_type_desc 按值降序比较,数值类型<字符串类型<数组类型,即num<str<arr
@val_str_asc 按值升序比较,数值转化成字符串再比较,而数组出现在尾部
@val_str_desc 按值降序比较,数值转化成字符串再比较,而数组出现在头部
@val_num_asc 按值升序比较,字符串转换为数值再比较,而数组出现在尾部
@val_num_desc 按值降序比较,字符串转化成数值再比较,而数组出现在头部
  • 示例一,按值降序排序
root@debian:~/awk# awk '{arr[$0]=$0;PROCINFO["sorted_in"]="@val_num_desc"}END{for(idx in arr)print arr[idx]}'< <(seq 6)
6
5
4
3
2
1
root@debian:~/awk# 
  • 示例二,按索引降序排序
root@debian:~/awk# awk '{arr[$0]=$0;PROCINFO["sorted_in"]="@ind_num_desc"}END{for(idx in arr)print idx"-->"arr[idx]}'< <(seq 6)
6-->6
5-->5
4-->4
3-->3
2-->2
1-->1
root@debian:~/awk

三、awk统计行和单词出现次数

  • 示例一,统计次数并按照值排序:
root@debian:~/awk# awk '{arr[$0]++;PROCINFO["sorted_in"]="@val_num_asc"}END{for(idx in arr)print idx"-->"arr[idx]}' x.log
-->1
def-->1
mnopq-->1
xyz-->1
ghi-->2
abc-->3
root@debian:~/awk#
  • 示例二,统计单词出现次数:
root@debian:~/awk# cat x.log
abc
def abc
ghi
abc word
ghi   hello
xyz  world

mnopq
abc
root@debian:~/awk# awk '{for(i=1;i<=NF;i++){arr[$i]++}}END{for(idx in arr)print idx":"arr[idx]}' x.log
hello:1
def:1
mnopq:1
abc:4
world:1
ghi:2
xyz:1
word:1
root@debian:~/awk#
  • 示例三,统计tcp[6]出现的state次数
root@debian:~/awk# netstat -tanp|awk '/tcp6?/{arr[$6]++}END{for(idx in arr)print idx":"arr[idx]}'
LISTEN:20
CLOSE_WAIT:126
ESTABLISHED:4
root@debian:~/awk#

四、根据字段取出最大值

root@debian:~/awk# cat aaa.txt
file 100
dir 11
file 100
dir 11
file 102
dir 112
file 120
dir 119
root@debian:~/awk# awk '{if(arr[$1]<$2){arr[$1]=$2}}END{for(idx in arr) print idx":"arr[idx]}' aaa.txt
dir:119
file:120
root@debian:~/awk#

使用三目运算法简化:

root@debian:~/awk# awk '{arr[$1]=($2>arr[$1]) ? $2: arr[$1]}END{for(i in arr)print i":"arr[i]}' aaa.txt
dir:119
file:120

五、awk复合索引数组

  • 示例,逆时针倒转数据:
root@debian:~/awk# cat c.txt
1 2 3 4 5 6
2 3 4 5 6 1
3 4 5 6 1 2
4 5 6 1 2 3
root@debian:~/awk# awk '{nf=NF;nr=NR;for(i=1;i<=NF;i++){arr[NR,i]=$i}}END{for(i=1;i<=nf;i++){for(j=nr;j>=1;j--)if(j==1)printf "%s\n",arr[j,i];else printf "%s ",arr[j,i]}}' c.txt
4 3 2 1
5 4 3 2
6 5 4 3
1 6 5 4
2 1 6 5
3 2 1 6
root@debian:~/awk# awk '{nf=NF;nr=NR;for(i=1;i<=NF;i++){arr[NR,i]=$i}}END{for(i=1;i<=nf;i++){for(j=nr;j>=1;j--)if(j%nr==1)printf "%s\n",arr[j,i];else printf "%s ",arr[j,i]}}' c.txt
4 3 2 1
5 4 3 2
6 5 4 3
1 6 5 4
2 1 6 5
3 2 1 6
root@debian:~/awk#

将数组元素按照[NR,NF]的格式存储,END读取完整个文件并初始化数组之后,使用for循环格式化输出即可。

六、测试数据类型是否为数组

  • isarray(arr)可用于检测arr是否为数组,是则返回1,否则返回0。
  • 对比typeof(arr)可返回arr的数据类型,如果arr为数组,则返回”array”
    示例:
root@debian:~/awk# awk 'BEGIN{arr[a]="a";print typeof(arr)=="array";print isarray(arr);arr["null"];print length(arr)}'
1
1
2
root@debian:~/awk#
打赏 赞(2) 分享'
分享到...
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

转载请注明出处:北慕城南's Blog » awk进阶用法-