过滤掉文本中的重复行
测试文件还是用之前的arr.dat,用下面的命令可以很轻松的解决
- sort -u arr.dat
输出结果:
- 1005 8:12
- 1005 8:13
- 1006 7:45
- 1008 8:01
- 1012 7:46
- 1025 7:27
- 1028 7:49
- 1029 7:57
- 1034 7:26
- 1042 7:59
- 1051 7:51
- 1052 8:05
- 1101 7:32
这并没有用到awk,如果将问题再进一步,如何过滤掉第一列重复的数据?
- awk '{print $1}' arr.dat|sort -u
输出结果:
- 1005
- 1006
- 1008
- 1012
- 1025
- 1028
- 1029
- 1034
- 1042
- 1051
- 1052
- 1101
可以看到,第一列所有的重复数据都已经过滤掉了。
上面的程序用到了新的东西:管道符(|)
管道会将其左边的输出传到右边作为输入。在awk程序中有两种使用管道的语法,如下:
- awk output 指令 | "Shell 接受的命令"
- "Shell 接受的命令" | awk input 指令
上面的例子就是语法1的例子,awk '{print $1}' arr.dat会输出arr.dat的第一列,它会传给sort -u去重和排序,sort是shell命令。
对于语法2,看下面的例子:
- awk 'BEGIN {"date"|getline;print $1}'
输出结果:
- 2012年10月20日
好消息,在awk中输入指令只有一个:getline
实际上,awk程序是可以接收来自shell的输出的,可以看下面的例子:
- cat arr.dat|awk '{print $1}'
上面的语句跟下面的是等价的:
- awk '{print $1}' arr.dat
都是输出文件的第一列。
顺便也学习一下sort的用法:
- sort -k2,2 -u -r arr.dat
输出结果:
- 1005 8:13
- 1005 8:12
- 1052 8:05
- 1008 8:01
- 1042 7:59
- 1029 7:57
- 1051 7:51
- 1028 7:49
- 1012 7:46
- 1006 7:45
- 1101 7:32
- 1025 7:27
- 1034 7:26
上面的sort语句是将第二列去重并倒排序,
-k2,2指代的是取第二列,逗号前的2是域起点,后的2是域终点;
-u是去重
-r是倒序
如果不用sort怎么去重呢?试试下面的程序:
- awk '!a[$1]++' arr.dat
上面的语句在单引号之内只有一个表达式,没有输出,在awk中会默认输出整行。a数组以第一列的值为键,如果第二行有跟第一列一样的值,则 a[$1]++后的结果是1,再取反,就成了0,就不会再输出整行了,换句话说就是,第二个重复的列将不再输出。这也起到了去重的作用。
顺便说一下,上面这种方法不会更改数据的顺序,当我们需要保持行记录的顺序时,可以用这种办法。
本文转自 ustb80 51CTO博客,原文链接:http://blog.51cto.com/ustb80/1033624,如需转载请自行联系原作者