在vi中删除重复的行?


123

我有一个文本文件,其中包含一长串条目(每行一个)。其中一些是重复项,我想知道是否有可能(如果可以,如何)删除任何重复项。如果可能的话,我有兴趣在vi / vim中进行此操作。



4
这是1岁;那是10个月。所以,反过来。
Sydius

@Sydius现在的共识是优先考虑upvote计数(您也可以了解更多):meta.stackexchange.com/questions/147643/…而且这些不是重复的,没有提到Vim :-)
Ciro Santilli郝海东冠状病六四事件法轮功

Answers:



25

试试这个:

:%s/^\(.*\)\(\n\1\)\+$/\1/

它会搜索紧随其后的一个或多个副本的任何行,并将其替换为一个副本。

在尝试之前,请先复制文件。未经测试。


1
@hop感谢您为我测试。当时我无法访问vim。
肖恩

2
这为我显示了所有重复的行,但没有删除,我在这里错过了一步吗?
2012年

我很确定这也将突出显示一行,其后是具有相同“前缀”但更长的一行。
hippietrail 2015年

3
唯一的问题是,如果有多个重复项(同一行中有3个或更多行),则必须运行多次,直到所有重复项都消失了,因为这一次只能删除一组重复项。
奥尔塔

2
这样做的另一个缺点:除非重复的行已经相邻,否则这将无法工作。首先排序将是确保它们彼此相邻的一种方法。到那时,其他答案可能更好。
奥尔塔

23

从命令行执行:

sort file | uniq > file.new

1
这对于我来说非常方便,因为文件很大。谢谢!
拉菲德2014年

1
:sort u我的大文件一样,无法获得公认的工作答案。这项工作非常迅速且完美。谢谢!
Tgsmith61591

1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail 2015年

1
是的-我在2.3 GB的文件上尝试了此技术,而且速度惊人。
DanM

@hippietrail您在Windows PC上吗?也许您可以使用cygwin。
12431234123412341234123 '18年


6
g/^\(.*\)$\n\1/d

在Windows上对我有效。但是,必须首先对行进行排序。


1
这将删除其前缀的行之后的行:aaaa其后aaaabbaaaa错误地删除。
hippietrail 2015年

5

我将结合以上两个答案:

go to head of file
sort the whole file
remove duplicate entries with uniq

1G
!Gsort
1G
!Guniq

如果您想查看删除了多少重复的行,请在前后使用control-G检查缓冲区中存在的行数。


1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail 2015年

3

在可视线模式(Shift+ v)中选择线,然后选择:!uniq。那只会捕获重复出现的重复项。


1
请注意,这仅适用于安装了uniq程序的计算机,即Linux,Mac,Freebsd等
anteatersa 2014年

对于那些不需要排序的人来说,这将是最好的答案。如果您是Windows用户,请考虑尝试Cygwin或MSYS。
fx-kirin


0
:%s/^\(.*\)\(\n\1\)\+$/\1/gec

要么

:%s/^\(.*\)\(\n\1\)\+$/\1/ge

这是我为您提供的答案,它可以删除多条重复的行,而只保留一个不删除!


0

我会使用!}uniq,但只有在没有空行的情况下才可以使用。

对于文件中的每一行,请使用::1,$!uniq


0

此版本仅删除连续的重复行。我的意思是,仅删除连续的重复行。使用给定的地图,该功能确实会引起空白行的混乱。但是,如果更改REGEX以匹配行的开头,^它还将删除重复的空白行。

" function to delete duplicate lines
function! DelDuplicatedLines()
    while getline(".") == getline(line(".") - 1)
        exec 'norm! ddk'
    endwhile
    while getline(".") == getline(line(".") + 1)
        exec 'norm! dd'
    endwhile
endfunction
nnoremap <Leader>d :g/./call DelDuplicatedLines()<CR>

0

不使用vi / vim(用于非常大的文件)的另一种方法是从Linux命令行使用sort和uniq:

sort {file-name} | uniq -u

0

这为我工作两个.csv.txt

awk '!seen[$0]++' <filename> > <newFileName>

说明: 该命令的第一部分打印唯一的行,第二部分打印,即在中间箭头之后保存第一部分的输出。

awk '!seen[$0]++' <filename>

>

<newFileName>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.