我已经在Scala中编写了一个程序(考虑Java(如果您不了解Scala的话)来实现这一点。但是,也许有更快的C编写的本机工具能够更快地执行此操作?
更新:只要文件的大小接近2 GiB或更小,
awk '!seen[q4312079q]++' filename
解决方案对我来说似乎就可以正常工作,但现在我正在清理8 GiB文件,它不再起作用。在配备4 GiB RAM和配备4 GiB RAM和6 GiB交换功能的64位Windows 7 PC的Mac上,似乎占用了无限空间。鉴于这种经验,我并不热衷于在具有4 GiB RAM的Linux上进行尝试。#1 楼
在#bash(Freenode)上看到的awk
解决方案:awk '!seen[q4312078q]++' filename
评论
刚刚在2G文件上尝试过,在我的笔记本上花了三分钟。不错。我也尝试过uniq filename | awk'!seen [$ 0] ++',但这没有更快。
– mgjk
2012年1月27日19:27
@HashWizard:此命令不进行排序,但是消除了同一行的下一次出现
– Enzotib
17年5月14日在15:51
想知道此命令如何工作? -请参阅此处:unix.stackexchange.com/questions/159695/how-does-awk-a0-work
– Supergra
17-10-24在19:13
@MaxWilliams是的,可以正常工作,因为它们是随机分布的。
– setholopolus
18年1月19日在19:58
保留换行符或带有空格的行awk'/ ^ \ s *?$ / ||!seen [$ 0] ++'
–詹姆斯·奥布莱恩(James O'Brien)
20 Mar 13 '20 at 0:46
#2 楼
有一个使用标准实用程序的简单方法(这并不是显而易见的方法),除了运行sort
之外,该方法不需要大量内存,而!seen[seen
] {print} {seen[q4312079q] += 1}
在大多数实现中都针对大型文件进行了特定的优化(一种良好的外部排序算法)。此方法的优点是,它仅在专用实用程序内部的所有行上循环,而不会在解释语言内部循环。空格字符,您可以省去一些选项:
<input nl -b a -s : | # number the lines
sort -t : -k 2 -u | # sort and uniquify ignoring the line numbers
sort -t : -k 1n | # sort according to the line numbers
cut -d : -f 2- >output # remove the line numbers
对于大量重复,该方法只需要在内存中存储每行的一个副本会表现更好。通过一些解释开销,有一个非常简洁的awk脚本(已由enzotib发布):
<input nl | sort -k 2 -u | sort -k 1n | cut -f 2- >output
简洁:q4312079q,即,如果没有,则打印当前行尚未看到,然后增加该行的q4312079q计数器(未初始化的变量或数组元素的数值为0)。每行的校验和(例如,加密摘要)。例如,使用SHA-1,您只需要20个字节加上每行恒定的开销。但是计算摘要相当慢。仅当您具有快速的CPU(尤其是带有硬件加速器以计算摘要的CPU)并且相对于文件大小和足够长的行没有足够的内存时,此方法才会成功。没有基本的实用程序可让您为每一行计算校验和。您必须承担Perl / Python / Ruby /…的解释开销,或者编写专用的编译程序。
<input awk '!seen[<input perl -MDigest::MD5 -ne '$seen{Digest::MD5::md5($_)}++ or print' >output
]++'
评论
@Gilles根据您对awk'!seen [$ 0] ++'的解释,是否意味着如果awk看到2条重复的行,它将始终保留第一行并忽略所有后续行? (或者它将保留最后一个?)
–user779159
17年5月3日,11:12
@ user779159保留第一个:每个输入行要么立即打印(第一次出现),要么根本不打印(重复出现)。
–吉尔斯'所以-不再是邪恶的'
17年5月3日,11:30
但这与-u ...排序相比如何?
– HashWizard
17年5月13日在21:37
@HashWizard普通排序-u更改顺序。我的答案显示了保留顺序(准确地说是第一次出现的顺序)的解决方案。
–吉尔斯'所以-不再是邪恶的'
17年5月13日在21:42
@Gilles您会说,对于具有50%重复项的大文件(10G),它比sort -u更快?
– HashWizard
17年5月13日在21:43
#3 楼
sort -u big-csv-file.csv > duplicates-removed.csv
请注意,输出文件将被排序。
评论
速度不及其他答案中的awk命令,但从概念上讲很简单!
–约翰
2015年3月31日23:11
@Johann我经常在带有数十万(甚至数百万)短换行符终止字符串的文件上执行此操作。对于正在进行的实验,我很快就能得到结果。如果在反复运行的脚本中使用它可能会更重要,这样可以节省大量时间。
–弗拉迪斯拉夫(Vladislavs Dovgalecs)
15年3月31日在23:13
使用sort -u在排序过程中而不是之后删除重复项。 (并节省内存带宽),将其通过管道传输到另一个程序)。如果您还希望对输出进行排序,则这仅比awk版本好。 (关于此问题的OP希望保留其原始顺序,因此对于稍有不同的用例,这是一个很好的答案。)
– Peter Cordes
2015年9月14日15:39
对我来说,花了大约一分钟的时间来制作550万行文件(总计1.8 GB)。辉煌。
–马克斯·威廉姆斯(Max Williams)
18年1月4日在11:23
#4 楼
假设您有能力在内存中保留尽可能多的已重复数据删除的文件(如果确实确实将数据重复了100倍,那应该是20MiB +开销),则可以使用Perl轻松地做到这一点。 >$ perl -ne 'print unless $dup{$_}++;' input_file > output_file
这也保留了顺序。
如果需要,您可以从
%dup
哈希中提取每行的出现次数,作为补充免费赠金。如果您更喜欢
awk
,也应该这样做(与perl版本相同的逻辑,相同的顺序,在dup
变量中收集的相同数据):$ awk '{if (++dup[q4312078q] == 1) print q4312078q;}' input_file > output_file
评论
@Mat太好了,我正要把文件lur住,大声笑;-)。
– Nikhil Mulley
2012年1月27日16:10
现在也等待@ManAtWork来获取他的sed和awk魔术织布工:-)
– Nikhil Mulley
2012年1月27日在16:11
再次为awk提示很棒:-)
– Nikhil Mulley
2012年1月27日在16:18
是否可以将perl脚本更改为仅删除重复的相邻行?
– dumbledad
16 Mar 10 '16 at 0:11
@dumbledad:uniq自己完成所有操作
–垫子
16 Mar 10 '16 at 5:50
#5 楼
由于没有其他任何就地支持的答案,所以这里是一个:gawk -i inplace '!a[q4312078q]++' file
评论
这会保留订单吗?顺便说一句,这对我不起作用。我的版本是:GNU Awk 4.0.2
–狮子座
17-2-16在10:31
@Leonid是的,确实如此。它打印任何唯一行的第一个匹配项。就地支持于2013年发布的4.1版中首次引入。
–rindeal
17年2月16日在12:49
这应该是答案。它实际上是删除现有文件或当前文件中的重复字符串,其中最上面的答案和此处的大多数答案仅打印出uniq /重复的字符串,并且什么也不做,我们必须创建另一个输出来存储结果。
– MaXi32
20 Jun 6'8:33
#6 楼
您可以使用uniq
http://www.computerhope.com/unix/uuniq.htm uniq
报告或过滤掉文件中的重复行。评论
给出答案时,最好对原因做出一些解释。那么,这个答案与之前的几个答案有何不同?
–斯蒂芬·劳赫(Stephen Rauch)
17 Mar 24 '17 at 4:08
在uniq手册页上:注意:“ uniq”不会检测到重复的行,除非它们相邻。因此,您必须首先对其进行排序,然后松开非重复行的顺序。
–温多林
18年11月6日在7:27
#7 楼
Python One衬板:python -c "import sys; lines = sys.stdin.readlines(); print ''.join(sorted(set(lines)))" < InputFile
评论
这会导致整个文件被拖入内存中,可能无法很好地解决OP的问题。也不能保证保留订单
– iruvar
2013年9月15日14:50
感谢您的建议,我一直在学习python ..只是出于学习目的尝试了此.. :)
–拉胡尔·帕蒂尔(Rahul Patil)
2013年9月15日19:52
这是Python 2.7版本,它不是单行的,而是(简洁地)返回保留行的唯一行,而无需将整个文件加载到内存中或创建单个巨型字符串以供打印
– iruvar
2013年9月16日下午16:37
谢谢@ 1_CR,我今天学到了一些东西:) OrderedDict
–拉胡尔·帕蒂尔(Rahul Patil)
2013年9月16日下午16:39
#8 楼
在我的Mac上,这里没有答案对我有用,所以我写了一个对我有用的简单python脚本。我不理会前导/尾随空格,也不在乎内存消耗。import sys
inputfile = sys.argv[1]
outputfile = sys.argv[2]
with open(inputfile) as f:
content = f.readlines()
content = [x.strip() for x in content]
my_list = list(set(content))
with open(outputfile, 'w') as output:
for item in my_list:
output.write("%s\n" % item)
#9 楼
无需维护原始序列命令的解决方案我使用以下代码段进行了处理。
sort duplicates.txt | uniq > noDuplicates.txt
sort
命令按字母顺序对行进行排序,而uniq
命令则删除重复项。 :为什么我们首先对行进行排序是因为uniq
除非相邻行,否则它们不会检测到重复行。评论
这个问题要求一种方法(最好是)来保持输入顺序。您可以编辑答案来解决这个问题吗?请注意,现有的使用排序的答案保持输入顺序,而使用排序的一个答案不保持输入顺序,但比通过管道传递给uniq更有效。
–斯蒂芬·基特(Stephen Kitt)
20 Sep 7 '14:01
@StephenKitt编辑。我检查了其他答案,但仅使用基本命令找不到任何内容。感谢您的反馈意见。
–ÇağlayanDÖKME
20/09/07在14:18
我给了您一个仅包含基本命令的答案的链接,实际上只有一个命令,排序-u(它是POSIX的一部分);-)。
–斯蒂芬·基特(Stephen Kitt)
20 Sep 7'14:25
@StephenKitt我看到了这个答案。我的也是解决问题的一种方法。您要我做什么?我应该删除答案吗?
–ÇağlayanDÖKME
20年9月7日在15:48
不,不要删除您的答案;我只是想确保您知道其他答案,因为您说过“只有基本命令才能找到任何东西”。
–斯蒂芬·基特(Stephen Kitt)
20年9月7日在15:59
#10 楼
对于bash 4,可以使用利用关联数组的纯bash解决方案。这是一个示例unset llist; declare -A llist;
while read -r line; do
if [[ ${llist[$line]} ]]; then
continue
else
printf '%s\n' "$line"
llist[$line]="x"
fi
done < file.txt
评论
不要使用读取循环来处理大文本文件。 bash必须一次读取一个字节,以免换行过头。与awk相比,bash在文本处理方面也不是很快。如果您确实使用了此选项,则读-ra将避免在输入中吃反斜杠。另外,如果将其放在shell函数中或以交互方式使用它,也不要忘记在循环后取消设置llist。
– Peter Cordes
2015年9月14日15:44
@PeterCordes,或者您可能刚刚引用了这个:-)
– iruvar
2015年9月14日20:41在
评论
这会破坏您的订购,但是,您是否尝试过排序-u,我不知道它如何或是否可以在如此大的文件上运行C通常不会比Java快很多,如果现在(按顺序)运行C,很有可能它会在您得到答案,实现它并完成运行之前完成。乱序排序-u可能会更快。