之前有用正则表达式写过一个重复两行压缩成一行的命令,今天我们来看一个讲重复多行压缩成一行的命令。 首先,我们先考虑怎么查出多个重复行。 有两种方法,但是有一种是有bug的,罗列如下:
1)
^\(.*\)\(\n\1\)\+$
2)
^\(.*\n\)\(\1\)\+
详细讲解一下:\+是代表匹配>1个,\1代表是前面的匹配,那么可以看出: 第1种方法是匹配了整个行(不包括换行符),然后加上\n\1,匹配\n\1 >1次,最后匹配到最后一个重复行行尾的换行符,从而匹配到所有重复行。 如图:
第2种方法则是先匹配了整个行(包括换行符),然后匹配\1 >1次,最后匹配到所有重复行。 如图:
但是实际上第二种匹配规则是有bug的,即假设最后一个重复行后面再也没有换行符的话,那么是匹配不到的,如图: 第一种方法:
第二种方法:
到此为止,既然查找的方法已经出来了,那么替换的方法也就有了
:%s/^\(.*\)\(\n\1\)\+$/\1/
OK,就到这里啦~~~
niejieqiang on #
有这样的十几万行:
bbllllllllll
bbmmmmkdjk
aaakkkkk
aaaccccccdd
dddd8888
dddd9999999
他们的特点是字符串前面有1-4个字母相同,我想把这样的行全都删除, gvim中怎么操作?(不是保留一行)
a行,b行和d行都是不同的行, 并且这文件中估计有将近一万这样重复的行.
十万火急, 先谢谢了. 我的邮箱 niejieqiang@gmail.com
Reply
Dante on #
g/\(\D\)\1\{3}/s/.*\n//g
哈,试试~~
Reply
Dante on #
补充一下,你说的是字母,所以上面的那个答案是只针对a~z和A~Z的,如果也包括数字的话,用这个:
g/\(\S\)\1\{3}/s/.*\n//g
Reply
niejieqiang on #
啊,还保留了一行啊,已经 非常谢谢了。
Reply
Dante on #
不好意思,之前写的有bug,可能会有一些匹配行未被删除,用这个命令可以解决:
%s/.*\(\S\)\1\{3}.*\n//gc
Reply
Also on #
呵呵。老兄真是乐于助人哈。不过写regex来处理有规律的字符串确实很有意思。
Reply
依云 on #
其实可以用:sort的。不要同时排序的话就像这样::sor ur /^/
Reply
依云 on #
根据文档这样做似乎不一定行,因为 :sort 不保证是稳定的。不过用 /$^/ 就可以了。
Reply
niejieqiang on #
非常感谢!!!!!
Reply
路人甲 on #
这个问题,我捣鼓了一天一夜,也google看到了很多方法。最后我把能用的我告诉大家
:sort
:g/\%(^\1$\n\)\@<=\(.*\)$/d
上楼依云说的方法也对。不过最好先拍下序
:sort
:sor ur /^/
别说说的很多方法都有很多bug,不亲自拿出几十万条数据测试根本发现不了,我用20条数据测试,基本上没种方法全是对的,但是我拿出1000条数据测试后,只有上面两种方法正常,其他的都有或多或少的没考虑到的地方,各种bug,没发上图,不能详细说明。
希望大家能早日看到这个评论,不要像我搞了一天一夜没睡。
Reply
Dante on #
呃,没太理解,是说文中的方法有bug吗?
Reply
路人甲 on #
http://blog.csdn.net/sasake/article/details/7170958
还望您指点
Reply