awk技巧-!a[$0]++

上一篇 / 下一篇  2012-04-06 00:24:18 / 个人分类:AWK学习

解释下
awk '!a[$0]++' file

一看之下,首先是想到又用到awk的hash,又是缺省的pattern,一下子来了兴趣,做了以下的分析

这个要从awk的执行模式开始说,最后结合++运算符,和hash特色
有三个基本知识点是要了解的
1:a++的作用是先附值,再累加a,与++a正好相反。

2:hash的初始是undef,通过直接附值或声明进行定义,如a[1]=1,或直接声明a[1]。

3:awk的基本模式是,pattern   { action statements },action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action。比如1,最简单的awk用来实现cat的功能就是 awk '1',这边1就是pattern,当然,1也可以是2,3,4,5等其他数字,但如果用字母的话,就不行,因为字母会解释成变量,变量初始值未定义,初始值为假,或者可以加个!反义

结合上边三点来分析awk '!a[$0]++' file
"!a[$0]++"

0:整个模式,没有用到action,所以采用的是默认的{print $0},即在patten为真条件来,输出行
patten分析:
1:使用了一个hash数组,a,数组的键值采用$0,即每行值
2:当a[$0]未声明时,a[$0]为假,在未声明的情况下,进行一次a[$0]++后,a[$0]即为真
3:!取反
结论:当相同的行第一次读入时,pattern为真,行输出,再次读入后,patten为假,行乎略

基本理论知道了,要用得出来还得多锻炼应用

上周帮别人写个awk,也是这种情况
我写的
awk '{if($2 in a);else{a[$2]=$0}}END{for(b in a)print a[b]}' urrfile

后来别人给出更简单的答案
awk ' !($2 in i){ i[$2]; print } ' urrfile

现在看来,还可以更简单些
awk '!a[$2]++' urrfile


【注意】:这是前加/后加的区别,前几天还说过。


   后加: 先使用变量的值,再自加。

   !a[$0]++ 对这个表达式的求值,它的值与 !a[$0] 相同(先使用变量a[$0]的值),但对表达式求值后 a[$0]会自加。


TAG:

abinNO1的个人空间 引用 删除 abinNO1   /   2013-03-20 21:39:49
6、关联数组关联多个字段:
awk 'NR==FNR{a[$3]=$1" "$2}NR>FNR&&b=$6{print $0,a[b]}' b a
abinNO1的个人空间 引用 删除 abinNO1   /   2013-03-20 21:39:15
1、将比较 file1的1-4字符 和 file2的2-5 字符,如果相同,将file2 的第二列 与 file1 合并
awk  'NR==FNR{a[substr($1,2,5)]=$2}NR>FNR&&a[b=substr($1,1,4)]{print $0, a[b]}' a b
abinNO1的个人空间 引用 删除 abinNO1   /   2013-03-19 16:58:09
awk调用shell外部函数:
export -f getmacinfo
                awk -v vi="$vi" -v vs="$hostid_ip $vmstate" 'BEGIN{while("getmacinfo '"$vd"'"|getline d){print vi,d,vs}}'
abinNO1的个人空间 引用 删除 abinNO1   /   2012-07-05 18:56:30
列求和。
ll -th|awk 'BEGIN{total=0}{total+=$2}END{print total}'
abinNO1的个人空间 引用 删除 abinNO1   /   2012-05-30 13:53:22
1、awk进行数值计算:
echo ""|awk '{print 3+4}'
abinNO1的个人空间 引用 删除 abinNO1   /   2012-05-25 14:31:31
打印某字符串对应列:
1、awk '{for(i=1;i<=NF;i++){if($i=="Country")print i}}' data.txt|xargs -i awk 'NR>1{print ${}}' data.txt

2、awk '/Country/{for(i=1;i<=NF;i++)if($i~/Country/)a=i}(a){print $a}' data.txt
abinNO1的个人空间 引用 删除 abinNO1   /   2012-05-16 17:14:18
1、删除第一个字段重复的且第二个字段为0的行:
awk 'NR==FNR{a[$1]++;next}$2!=0||a[$1]==1' test.info test.info
PBCSPOFT0101    96                           
PBCSPOFT0102    6
PBCSPOFT0103    8
PBCSPOFT0104    0
PBCSPOFT0105    0
PBCSPOFT0106    0
PBCSPOFT0107    10
PBCSPOFT0108    0
abinNO1的个人空间 引用 删除 abinNO1   /   2012-05-16 17:11:09
1、a[$1]在未声明之前为假。
2、第二次读取同一个文件的时候,a[$1]并不累加,而是直接饮用第一次读取文件的那个值。
awk 'NR==FNR{print NR,$0,a[$1],a[$1]++,a[$1]}NR>FNR{print NR,$0,a[$1]}' test.info test.info
1 PBCSPOFT0101    0                              0 1
2 PBCSPOFT0101    96                             1 1 2
3 PBCSPOFT0102    0  0 1
4 PBCSPOFT0102    6 1 1 2
5 PBCSPOFT0103    0  0 1
6 PBCSPOFT0103    8 1 1 2
7 PBCSPOFT0104    0  0 1
8 PBCSPOFT0105    0  0 1
9 PBCSPOFT0106    0  0 1
10 PBCSPOFT0107    0  0 1
11 PBCSPOFT0107    10 1 1 2
12 PBCSPOFT0108    0  0 1
13 PBCSPOFT0101    0                             2
14 PBCSPOFT0101    96                             2
15 PBCSPOFT0102    0 2
16 PBCSPOFT0102    6 2
17 PBCSPOFT0103    0 2
18 PBCSPOFT0103    8 2
19 PBCSPOFT0104    0 1
20 PBCSPOFT0105    0 1
21 PBCSPOFT0106    0 1
22 PBCSPOFT0107    0 2
23 PBCSPOFT0107    10 2
24 PBCSPOFT0108    0 1
 

评分:0

我来说两句

Open Toolbar