Vim去除重复行


Vim去除重复行

方法一:

先sort排序,再去重

:sort  //直接排序
:g/^\(.*\)$\n\1$/d                      //去除重复行
:g/\%(^\1$\n\)\@<=\(.*\)$/d    //功能同上,也是去除重复行
:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d  //功能同上,也是去除重复行

方法二:使用awk

awk ‘!a[$0]++’ file

解析:

awk流程是逐行处理的,默认从文件的第一行一直处理到文件最后一行,还要知道awk的基本命令格式是'pattern{action}'先匹配各种各样的样式,然后大括号里处理如何打印输出,默认的只要匹配了pattern就{print $0},如果pattern未命中其判断值为假(0)那么就不会再去处理{action}了;pattern命中则为判断值为真(非0)就去处理{action}。
举个最简单的例子:awk '1' file和awk '{print $0}' file是一个道理,都是从头到尾依次打印文件的每一行。


'!a[$0]++'
分成几个部分简单解释下吧。
这个命令没有{action}也就是说,只要pattern部分判断值为真(非0)就打印该行,否则就跳过不打印
!在awk是取相反的意思,就是把对的变成错的把真的变成假的,放在这个命令中是神马作用一会解释;
a[$0]这个非常好理解,建立数组a,其变量是文本中的每一行,awk里$1是第一列,$2是第二列,以此类推$NF是最后一列,而$0是代表所有列及分隔符,也就是一整行,这样如果pattern是真的那就打印一整行
++的意思是a数组取变量完毕后,对该数组值+1
找个最简单的文档来解释一下


cat file
xxx
yyy
xxx
zzz


这个文件有4行,其中第一、三行是重复的。套用这个命令处理流程如下:
获取第一行a[xxx],因为这是第一行,数组a里从没见过xxx这个变量,那么自然他的值就是假(0)也就是说a[xxx]=0,这个时候!就有大作用了,他把a[xxx]假(0)变成了a[xxx]为真(!0)这个时候原本不该打印的第一行就变成了应该打印了,取逻辑反后对a[xxx]的值+1然后处理第二行
第二行a[yyy]这个情况跟刚才第一行的a[xxx]一样,也应该打印他
到第三行的时候情况变了,因为第一行已经出现过a[xxx]并且已经++过了,他的值已经是非0而不是前两行的0了,本应打印但这时候再由!取逻辑反就不必打印了
第四行a[zzz]就又和第一、二两行一样了。
所以执行完就是这个结果
awk '!a[$0]++' file
xxx
yyy
zzz

再把file搞稍微复杂点


awk '{print NR,$0}' file
1 xxx
2 yyy
3 zzz
4 xxx
5 yyy
6 zzz
7 xxx
8 yyy
9 zzz

一共9行文本,3行一次重复。为了看得更清楚,本来默认的{print $0}稍微改下,变成{print NR,$0}。 NR表示行号。
那么现在来执行下刚才讲的试试看

awk '!a[$0]++{print NR,$0}' file
1 xxx
2 yyy
3 zzz

awk 'a[$0]++{print NR,$0}' file
4 xxx
5 yyy
6 zzz
7 xxx
8 yyy
9 zzz

很明显了吧,有!的命令是只打印第一次出现的$0也就是去除重复咯,而没有!的命令正好跟他相反,就是仅仅去除第一次出现的$0。

推荐阅读:

Vim学习指南

快速学会 Vi编辑器

强大的Vim 编辑器

在CentOS 6.2上搭建Vim开发环境

Vim 7.4a 发布,全新更快的正则表达式引擎

CentOS 5.4 安装高亮Vim编辑工具

Vim技巧分享:C语言设置

Ubuntu中设置Vim的行号

Vim编辑器使用基础教程

相关内容