今天在做数据分析的时候,需要对原始文件做排重处理,网上看到一个方式如下所示
root@localhost cc]# cat 2.txt
adc 3 5
a d a
a 3 adf
a d b
a 3 adf
去重第一列重复的行:
[root@localhost cc]# cat 2.txt |awk ‘!a[$1]++{print}‘
adc 3 5
a d a
重复的行取最上面一行记录
去重以第一列和第二列重复的行:
[root@localhost cc]# cat 2.txt |awk ‘!a[$1" "$2]++{print}‘
adc 3 5
a d a
a 3 adf
但是按照awk模式
理解,上面的语法是没有用到BEGIN
和 END
, 那就是主体block
, 但是主体block
的语法为 /pattern/ {command}
,有感觉不符合
分析
1、上面语句中的{print}
默认是打印所有符合条件的列, 是 print $0
的简写,
2、a[$1]++
拆分开来看,a[$1]
是把第一列作为数组下标,也就是 a[$1]
的结果是个数字
这样才能执行后面的++
操作
3、既然如此,那就改造语句执行如下
root@pts/0 $ cat repeat.txt |awk '{print a[$1]++, $0}'
0 adc 3 5
0 a d a
1 a 3 adf
2 a d b
3 a 3 adf
root@pts/0 $ cat repeat.txt |awk 'a[$1]++{print}'
a 3 adf
a d b
a 3 adf
4、从上面的对比结果发现,非0的结果被输出,都是第一列出现重复
的,也就是存在 条件判断
? 做以下改造验证
root@pts/0 $ cat repeat2.txt |awk '{if (a[$1]++ > 0)print}'
a 3 adf
a d b
a 3 adf
和第3步的结果对比发现,确实做了条件判断
5、所以问题现在定位在两个方面,最主要的是数组中第一次出现的元素
的值为何是0
6、进过排查,针对awk数组
,有个特性是:
1、直接引用一个数组中不存在的元素时,awk会自动创建这个元素,并且为其赋值为"空字符串"
2、awk中,当变量a的值为字符串时,也可以进行加法运算,如果字符串参与运算,字符串将被当做数字0进行运算
3、空字符串也是字符串,参与运算时,也会被当做数字0进行运算
验证:
直接引用一个数组中不存在的元素时,awk会自动创建这个元素,并且为其赋值为"空字符串"
awk中,当变量a的值为字符串时,也可以进行加法运算,如果字符串参与运算,字符串将被当做数字0进行运算
空字符串也是字符串,参与运算时,也会被当做数字0进行运算
综上所述
1、条件判断是可以放到主体block{}
外面的
2、a[$1]++
遇到第一个出现的记录时,其实就是数组中不存在的一个元素,其默认是为空,计算是被当做0
所以上面的最上面例子中的语句等价于
root@pts/0 $ awk 'a[$1]++>0{print}' repeat.txt
a 3 adf
a d b
a 3 adf
root@pts/0 $ awk '{if(a[$1]++>0) print}' repeat.txt
a 3 adf
a d b
a 3 adf
refer:
[1] http://www.mamicode.com/info-detail-1616775.html
[2] https://www.jianshu.com/p/cae3cccd2ee6