目录
展开
一、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
次数
```bash
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#