Standing on the shoulders of Giants
hadoop distcp使用filters参数排除指定文件
ansible学习之十:Error Handling In Playbooks
Aug 7, 2014 • shell
很多人都知道awk '!a[$0]++' file
可以去除文本中重复的行,但是对其到底是如何去重的却不是很清楚,所以这里就单独来分析一下这个命令。
首先我们要知道这条命令是隐含了一个print $0
的,完整命令如下:
$ cat c
1
2
2
3
1
3
3
$ awk '!a[$0]++{print $0}' c
1
2
3
awk判定以下三种情况为“假”,其他情况都为“真”:
所以上面这条awk语句的原理就是判断!a[$0]++
的值,如果值为真就打印当前行,值为假自然就不会打印当前行了。
开始分析!a[$0]++
吧,不过还得先看一下awk中操作符的优先级(由高到低排列):
$ #字段引用($1,$2)
++ --
^ ** #求幂
+ - ! #正、负、逻辑非
* / %
+ - #加法减法
(blank) #连接符
< <= == != > >=
~ !~
&&
||
?:
= += -= *= /= %= ^= **=
这里看到++
操作符优先级是高于!
操作符的。
现在正式开始分析!a[$0]++
,先使用{print ">"a[$0]+0}
来输出每次进行!a[$0]++
计算后a[$0]
的值:
$ echo -e "5\n5\n5"|awk '{print ">"a[$0]+0}!a[$0]++{print $0}'
>0
5
>1
>2
为了简化输出,这里只对相同的三行进行去重,可以看到处理第一行之前a[$0]
还是未定义的,所以输出为空(这里通过a[$0]+0
强制转换成了0),当第一行处理完成之后a[$0]
的值变成了1,第二行处理完成之后a[$0]
的值变成了2,以此类推。
这里我们可以将a[$0]
数组取值替换为一个简单的变量,方便理解:
$ awk 'BEGIN{a=0;print !a++,a}'
1 1
$ awk 'BEGIN{a=1;print !a++,a}'
0 2
$ awk 'BEGIN{a=2;print !a++,a}'
0 3
我们知道a++
操作符是在变量a使用完之后再对变量进行自增,所以这里虽然++
比!
优先级高,先跟变量a结合,但是不会立即自增变量a的值,而是在!a
之后在自增变量a的值。通过例子来理解:
现在是不是一目了然了,再代入回之前的例子中:
$ echo -e "5\n5\n5"|awk '{print ">"a[$0]+0}!a[$0]++{print $0}'
>0
5
>1
>2
分析如下:
分析完成,不过这只是我个人的理解,有不对的地方请回复指出,一起学习!
下一篇:sed地址匹配总结