我有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中环,但因为我有大约150万项,它可能会需要一段时间的事实。
试试这个AWK一行代码:
awk '{a[$1]++;b[$1]=$0}END{for(x in a)if(a[x]==1)print b[x]}' file
这里是另一种方式:
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
没有一个班轮,但这个小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";
}
无法为注释正确格式。 @JS 웃可能依靠GNU uniq
...这似乎在BSD衍生版本一起使用:
grep ^`cut -d" " -f1 col_data.txt | uniq -u` file.txt
有简单的必须是一个较短的perl
回答:-)
我知道必须有一个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万条记录慢速运行i..e之一。 我想看看它相比awk
和uniq
虽然。
在加方不使用模块和应用在Windows和OSX上运行。 它的工作原理时,有独特的第一列几十个类似的记录,而且不需要前检查独特的行进行排序的输入。 该解决方案主要是从靠近末端的一个班轮例子那儿剽窃有效Perl编程约瑟夫·霍尔,荷兰Joh麦克亚当斯和布莱恩d FOY (一个伟大的书本-当智能匹配~~
并given when
尘埃落定,我希望新版本出现):
下面是它的(我认为)工作原理:
- 因为我们使用的
-a
我们得到的@F
免费数组所以使用它,而不是分裂 - 因为我们使用
-n
我们是一个内while() {}
循环,所以push
的元件@F
成@AoA
作为参考的匿名阵列(在[]
充当“匿名数组构造” )。 这样,他们流连,我们可以稍后再引用它们(这是否甚至意义???) - 使用
$seen{$_}++
成语(我们使用$S
代替$seen
)从上面提到和描述的那么好由书@Axeman这里SO看的独特元素@F[0]
并设置在我们的/增量键%S
根据多少次,我们看到与给定值( 即行内容)的元素(或线)哈希值。 - 使用一个“蝴蝶”
}{
打出来的的while
,然后,在一个单独的块,我们使用了两个for
循环要经过外阵列并检查每个元素(它们本身是匿名数组$i
-每个线)和然后,针对每个内部匿名数组, grep
哪些值与去keys
是等于“1” %S
我们先前创建散列(在for $j (grep {$S{$_}==1} keys %S)
,或内循环),并连续将这些值在$j
。 - 最后,我们通过外阵列迭代并打印任何匿名阵列,其中该阵列的第一个元素等于每个的值(
$j
)。 我们这样做有:( @{$AoA[$i]}[0]==$j
)。
awk
在@Kent手里有点更简练。 如果任何人有如何缩短或记录我的“线路噪声”的建议(我从来不说一下perl
!)请加建设性的意见!
谢谢阅读。