我有一个包含12列的txt文件。有些行是重复的,有些则不是。作为一个例子,我复制到我的数据的前4列。
0 0 chr12 48548073
0 0 chr13 80612840
2 0 chrX 4000600
2 0 chrX 31882528
3 0 chrX 3468481
4 0 chrX 31882726
4 0 chr3 75007624
根据第一列,您可以看到除了条目“3”之外还有一些重复项。 我想打印唯一的单个条目,在本例中为'3'。
输出
3 0 chrX 3468481
用awk或perl快速做到这一点吗?我只能想到在perl中使用for循环,但鉴于我有大约1.5M的条目,它可能需要一些时间。
答案 0 :(得分:4)
尝试这个awk one-liner:
awk '{a[$1]++;b[$1]=$0}END{for(x in a)if(a[x]==1)print b[x]}' file
答案 1 :(得分:3)
这是另一种方式:
uniq -uw8 inputFile
-w8
会比较第一个 8个字符(这是您的第一列)的唯一性。 -u
选项只会打印出现一次的行。 $ cat file
0 0 chr12 48548073
0 0 chr13 80612840
2 0 chrX 4000600
2 0 chrX 31882528
3 0 chrX 3468481
4 0 chrX 31882726
4 0 chr3 75007624
$ uniq -uw8 file
3 0 chrX 3468481
答案 2 :(得分:2)
不是单行,但是这个小的Perl脚本完成了同样的任务:
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
# get filehandle
open( my $fh, '<', 'test.txt');
# all lines from your file
my %line_map;
while( my $line = <$fh> ) { # read a line
my $key;
my @values;
# split on whitespace
($key, @values) = split(/\s+/, $line);
# delete a line if it already exists in the map
if( exists $line_map{$key} ) {
delete $line_map{$key};
}
else { # mark a line to show that it has been seen
$line_map{$key} = join("\t", @values);
}
}
# now the map should only contain non-duplicates
for my $k ( keys %line_map ) {
print "$k\t", $line_map{$k}, "\n";
}
答案 3 :(得分:1)
无法正确格式化评论。 @JS웃可能依赖于GNU uniq
......这似乎适用于BSD派生版本:
grep ^`cut -d" " -f1 col_data.txt | uniq -u` file.txt
必须有一个较短的perl
答案: - )
答案 4 :(得分:0)
我知道必须有perl
单行回复。这是 - 没有经过严格测试,所以警告经纪人; - )
perl -anE 'push @AoA,[@F]; $S{$_}++ for @F[0];}{for $i (0..$#AoA) {for $j (grep {$S{$_}==1} keys %S) {say "@{$AoA[$i]}" if @{$AoA[$i]}[0]==$j}}' data.txt
这种方法的缺点是它以略微修改的格式输出数据(这很容易修复,我认为)它使用两个for
循环和一个“蝴蝶操作符”(!!)它也使用grep()
(它引入了一个隐式循环 - 即代码运行的一个循环,即使你不必自己编写循环代码)所以它可能会有150万条记录。我希望看到它与awk
和uniq
进行比较。
从好的方面来看,它不使用任何模块,应该在Windows和OSX上运行。当有几十个具有唯一第一列的类似记录时,它可以工作,并且在检查唯一行之前不需要对输入进行排序。约瑟夫·霍尔,约翰·麦克亚当斯和Effective Perl Programming(一本很棒的书 - 当智能匹配~~
和{{}时,解决方案主要来自brian d foy末尾附近的单线示例。 1}}尘埃落定我希望出现新版本):
以下是(我认为)它如何运作:
given when
,因此我们免费获取-a
数组,因此使用它而不是拆分@F
我们在-n
循环中,所以while() {}
push
的元素作为@F
作为匿名参考数组(@AoA
充当"anonymous array constructor")。那样他们就会闲逛,我们可以在以后再引用它们(这是否有意义?)[]
惯用语(我们使用$seen{$_}++
代替$S
),@Axeman here on SO对{{3}}的独特元素进行了详细描述{1}}并根据我们看到具有给定值(即行内容)的元素(或行)的次数,在$seen
哈希中设置/增加键。@F[0]
来突破%S
然后,在一个单独的块中,我们使用两个}{
循环来遍历外部数组并检查每个元素(它们本身就是匿名数组while
- 每行一个),然后,对于每个内部匿名数组,for
哪些值与$i
一起在{{{1}中等于“{我们之前创建的哈希(grep
或内部循环)并连续将这些值放在keys
中。 %S
)的值。我们这样做:(for $j (grep {$S{$_}==1} keys %S)
)。 $j
有点精辟。如果有人有关于如何缩短或记录我的“线路噪音”的建议(我从未说过$j
!)请添加建设性意见!
感谢阅读。