我正在尝试找到一种方法来查找并仅打印文件中没有重复的行。如果这是我的文件:
A
A
B
B
C
C
Y
Z
我正在尝试仅打印
Y
Z
不幸的是,我不断
A
B
C
Y
Z
我尝试过sort -u
、sort | uniq -u
和,grep | sort | uniq -u
结果相同。我最终能够实现我的目标,即使用uniq -c
并寻找仅出现一次的线条来找到唯一的线条,但我想知道将来如何正确地做到这一点。
答案1
AWK 解决方案
$ awk '{arr[$0]++};END{for(var in arr) if (arr[var] == 1) print var}' input.txt
Y
Z
{arr[$0]++};
创建行号对的关联数组。如果某一行在文件中是唯一的,则与行值相对应的数组项将为 1,否则 - 大于 1END
当我们到达文件末尾时,将执行 block。我们使用for(value in array)
循环迭代数组项,如果相应的数组项等于 1,则打印该值,如前所述。
Python 3
与上一个想法相同awk
。这里我们使用OrderedDict
类来创建一个保留顺序的行和行计数字典。
#!/usr/bin/env python3
import sys
from collections import OrderedDict
if len(sys.argv) != 2:
sys.stderr.write(">>> Script requires a file argument")
sys.exit(1)
for arg in sys.argv[1:]:
lines = OrderedDict()
with open(sys.argv[1]) as fd:
for line in fd:
tmp = line.strip()
if tmp in lines.keys():
lines[tmp] = lines[tmp] + 1
else:
lines[tmp] = 1
for line,count in lines.items():
if count == 1:
print(line)
实际运行如下:
$ ./get_unique_lines.py input.txt
Y
Z
Perl
同样,与 Python 脚本的想法相同,我们使用有序哈希(也可以看看Tie::IxHash 文档)。
#!/usr/bin/perl
use strict;
use warnings;
use Tie::IxHash;
tie my %linehash, "Tie::IxHash" or die $!;
open(my $fp,'<',$ARGV[0]) or die $!;
while(my $line = <$fp> ){
chomp $line;
$linehash{$line}++;
}
close($fp);
for my $key (keys %linehash) {
printf("%s\n",$key) unless $linehash{$key} > 1;
}
测试运行:
$ ./get_unique_lines.pl input.txt
Y
Z
sort 和 uniq 变体
评论中已经多次提到过。
$ sort input.txt | uniq -u
Y
Z
或者
$ uniq -u input.txt
Y
Z