我需要删除文件中多次出现的所有行。删除重复的行(包括重复的行)
实施例:
Line1
Line2
Line3
Line2
结果:
Line1
Line3
Python和Perl或UNIX的UTIL,无所谓。谢谢。
我需要删除文件中多次出现的所有行。删除重复的行(包括重复的行)
实施例:
Line1
Line2
Line3
Line2
结果:
Line1
Line3
Python和Perl或UNIX的UTIL,无所谓。谢谢。
这是一个Python实现。
如果您需要保存线的初始订单:
import collections
import fileinput
lines = list(fileinput.input())
counts = collections.Counter(lines)
print(''.join(line for line in lines if counts[line] == 1))
如果不是,它是一点点简单和快速):
import collections
import fileinput
counts = collections.Counter(fileinput.input())
print(''.join(line for line, count in counts.iteritems() if count==1))
对于每一行,你需要看如果它有任何dups。如果您不希望以二次方式执行此操作(执行一次传递,然后再执行每一行的第二次传递),则需要使用中间数据结构,该结构允许您以两次线性传递完成此操作。
所以,你通过列表来构建一个散列表(collections.Counter
是一个专门的dict
,只是将每个键映射到它出现的次数)。然后,您可以在列表中进行第二遍,在散列表(第一个版本)中查看每一个,或者迭代散列表(第二个)。
据我所知,没有办法与命令行工具做等价的事情;你至少需要输入sort
(它是O(N log N),而不是O(N)),或者使用一个隐式执行等价操作的工具。
但是对于很多用例来说,这不是什么大不了的事情。对于具有1M行的80MB文件,N log N仅比N慢一个数量级,并且完全可以想象,两个工具之间的常数乘数差异将是相同的。
快速计时测试验证,在1M的线路规模,sort | uniq -u
版本是刚刚超过6倍的速度较慢,但仍然不够快,你可能不会关心(不足10秒,这是更多的时间比复制和粘贴Python代码要复杂得多,对吧?),除非您必须重复执行此操作。
从进一步的测试,在128K行,Python版本只有4倍的速度;在64M线上,速度提高了28倍;在5G线...两个版本驱动系统进入交换抖动足够严重,我杀死了测试。 (更换Counter
有dbm
键值数据库解决了这个问题,但对于小规模巨大的成本。)
对不起,我忽略了关于测试的一点。评论撤回。 – ikegami 2013-04-30 19:35:47
读每一行,用grep线在同一文件中找到的计数,仅打印那些其中计数为1:
#!/bin/bash
while read line
do
if [ `grep -c ${line} sample.txt` -eq 1 ] ; then echo ${line} ; fi
done < sample.txt
下面是perl的一个例子:
my %line_hash;
open my $fh, "<", "testfile";
while(my $line = <$fh>) {
$line_hash{$line}++;
}
close $fh;
open my $out_fh, ">>", "outfile";
for my $key (sort keys %line_hash){
print $out_fh $key if $line_hash{$key} == 1;
}
close $out_fh;
testfile的:
$ cat testfile
Line1
Line2
Line3
Line2
OUTFILE:
$ cat outfile
Line1
Line3
果脯秩序,但保留在内存中的文件的两个副本:
my @lines;
my %seen;
while (<>) {
push @lines, $_;
++$seen{$_};
}
for (@lines) {
print if $seen{$_} == 1;
}
作为一个班轮:
perl -ne'push @l, $_; ++$s{$_}; }{ for (@l) { print if $s{$_} == 1; }'
不维持秩序,但保存在内存只有一个文件的副本:
my %seen;
++$seen{$_} while <>;
while (my ($k, $v) = each(%seen)) {
print $k if $v == 1;
}
作为一个班轮:
perl -ne'++$s{$_}; }{ while (my ($k, $v) = each(%s)) { print $k if $v == 1; }'
从一个快速测试,这些似乎工作。扫描代码,它们在功能上与我的两个Python实现完全相同,大小相同,速度+/- 50%,内存使用类似。据推测,对于熟悉Perl但不熟悉Python的人来说,它会更易读,并且从快速测试中看来似乎可行。所以... +1。您可能想要阅读其他perl的答案,因为我不确定它是否相同。 (我很早以前就故意用电极烧掉我的大脑中读取perl的那部分内容。) – abarnert 2013-04-30 18:07:48
@abarnert,是的,它实际上非常干净的Perl代码,但Perl看起来与其他语言有点不同,所以它可能很难读给外人看。 ///我看到了另一个Perl的答案。它使用尽可能多的内存作为我的订单保存解决方案,但它不能保持顺序。 (它也可以分类,尽管它只是出于美学原因,所以如果性能是一个问题,它可以被删除。) – ikegami 2013-04-30 19:43:01
您是否需要保留原始订单? – abarnert 2013-04-30 17:05:58
这个问题已经回答了几次;检查[this] [1]。 [1]:http://stackoverflow.com/questions/1215208/how-might-i-remove-duplicate-lines-from-a-file – 2013-04-30 17:06:26
否的顺序并不重要。 – tor11 2013-04-30 17:08:52