4

我有一个制表符分隔的文件,看起来像这样

chr1  12226559  12227059  TNFRSF1B       
chr1  17051560  17052060                 
chr1  17053279  17053779                 
chr1  17338423  17338923  ATP13A2        
                          ATP13A2        
                          ATP13A2        
chr1  19577574  19578074  EMC1           
                          MRTO4          
chr1  19578046  19578546  EMC1           
                          MRTO4          
chr1  19638239  19638739  AKR7A2         
                          PQLC2          
                          PQLC2          
                          PQLC2
                          AKR7A2         
                          PQLC2     

我希望删除 column4 值重复的行。

前三列是坐标,在这些坐标中列出了我们找到的任何内容(在 col4 中),对于每个坐标,我只想有唯一的名称而不是重复的名称。

我想要这样的输出

chr1  12226559  12227059  TNFRSF1B       
chr1  17051560  17052060                 
chr1  17053279  17053779                 
chr1  17338423  17338923  ATP13A2              
chr1  19577574  19578074  EMC1           
                          MRTO4          
chr1  19578046  19578546  EMC1           
                          MRTO4          
chr1  19638239  19638739  AKR7A2         
                          PQLC2 

我尝试过的事情

sort -k 4 -u file

awk '{if($4==temp1){next;}else{print}temp1=$4}' file

没有任何效果:(

请帮忙

谢谢

4

7 回答 7

4

您只需

awk '$NF != prev {print} {prev=$NF}'

编辑:处理新的输入

awk '{
    if (NF == 1) 
        value = $1
    else {
        key =  $1 SUBSEP $2 SUBSEP $3
        value = $4
    }
    if ((key SUBSEP value) in val) 
        next
    print
    val[key, value] = 1
}' input
于 2012-11-19T17:59:42.123 回答
2
sed '1{x;d};H;x;s/\([ ][^\n ]*\)[ ]*\n[ ]*\1[ ]*\n/\1\n/;$p;x;d;$p;x;d' FILE

如果您的文件中有标签,除了空格,您可以将所有标签替换[ ][[:space:]].

于 2012-11-19T17:30:11.003 回答
1

使用一个小perl脚本:

perl -e 'my $col4 = "";
while (<>) {
  chomp;
  my @f = split(/\t/, $_);
  if ($f[3] eq "" || $f[3] ne $col4) {
    print $_, "\n";
  }
  $col4 = $f[3];
}' input.txt

结果:

chr1    12226559        12227059        TNFRSF1B
chr1    17051560        17052060
chr1    17053279        17053779
chr1    17338423        17338923        ATP13A2
chr1    19577574        19578074        EMC1
                                        MRTO4
chr1    19578046        19578546        EMC1
                                        MRTO4
chr1    19638239        19638739        AKR7A2
                                        PQLC2
于 2012-11-19T15:03:12.280 回答
1

简单的awk脚本

awk -F'\t' '{OFS="\t"; if ($4=="" || $4!=old) print; old=$4}' input.txt

结果

chr1    12226559        12227059        TNFRSF1B
chr1    17051560        17052060
chr1    17053279        17053779
chr1    17338423        17338923        ATP13A2
chr1    19577574        19578074        EMC1
                                        MRTO4
chr1    19578046        19578546        EMC1
                                        MRTO4
chr1    19638239        19638739        AKR7A2
                                        PQLC2

打扫

为了准备我的input.txt文件,我从问题中复制了文本。但我不得不用制表符替换空格。因此我使用了一个sed命令。我还注意到一些尾随空格(在行尾)。最后,我使用以下sed命令清理输入文件:

sed 's/ *$//;/^[^ ]/s/  */\t/g;/^ /s/  */\t\t\t/g;' copy-fron-so.txt > input.txt

来自@dogbane 评论的输入文件

chr1  12226559  12227059  TNFRSF1B
chr1  17051560  17052060
chr1  17053279  17053779
chr1  17338423  17338923  ATP13A2
                          ATP13A2
                          ATP13A2
chr1  19577574  19578074  EMC1
                          MRTO4
chr1  19578046  19578546  EMC1
                          MRTO4
chr1  19638239  19638739  AKR7A2
                          PQLC2
                          PQLC2
                          PQLC2
                          AKR7A2

(最后一行已附加)

清洗和加工

$> sed 's/ *$//;/^[^ ]/s/  */\t/g;/^ /s/  */\t\t\t/g;' copypaste.txt > input.txt
$> awk -F'\t' '{OFS="\t"; if ($4=="" || $4!=old) print; old=$4}' input.txt
chr1    12226559        12227059        TNFRSF1B
chr1    17051560        17052060
chr1    17053279        17053779
chr1    17338423        17338923        ATP13A2
chr1    19577574        19578074        EMC1
                                        MRTO4
chr1    19578046        19578546        EMC1
                                        MRTO4
chr1    19638239        19638739        AKR7A2
                                        PQLC2
                                        AKR7A2

需求变化

AKR7A2不应打印最后一行。因此,我们首先需要对input.txt文件进行排序。小心该选项-t用于引入一个选项卡,然后按bashvi[CTRL-V],然后[TAB](在此选项卡周围加上引号)。

$> LANG=C sort -k 4 -s -t ' ' input.txt > sorted.txt 
$> awk -F'\t' '{OFS="\t"; if ($4=="" || $4!=old) print; old=$4}' sorted.txt
chr1    17051560        17052060
chr1    17053279        17053779
chr1    19638239        19638739        AKR7A2
chr1    17338423        17338923        ATP13A2
chr1    19577574        19578074        EMC1
                                        MRTO4
                                        PQLC2
chr1    12226559        12227059        TNFRSF1B

请注意,有一行以MRTO4now 结尾!

于 2012-11-19T15:42:11.603 回答
1

也许以下内容会有所帮助:

use strict;
use warnings;

my %seen;

while (<DATA>) {
    my ($col3) = (split)[-1];
    print if !$seen{$col3}++ or !$col3;
}

__DATA__
chr1    12226559    12227059    TNFRSF1B
chr1    17051560    17052060    
chr1    17053279    17053779    
chr1    17338423    17338923    ATP13A2
                                ATP13A2
                                ATP13A2
chr1    19577574    19578074    EMC1
                                MRTO4
chr1    19578046    19578546    EMC1
                                MRTO4
chr1    19638239    19638739    AKR7A2
                                PQLC2
                                PQLC2
                                PQLC2

输出:

chr1    12226559    12227059    TNFRSF1B
chr1    17051560    17052060    
chr1    17053279    17053779    
chr1    17338423    17338923    ATP13A2
chr1    19577574    19578074    EMC1
                                MRTO4
chr1    19638239    19638739    AKR7A2
                                PQLC2

此输出也可以通过以下单行实现:

perl -ane "print if !$X{$F[-1]}++ or !$F[-1]" data.txt
于 2012-11-19T17:41:31.457 回答
1

鉴于我将使用的新发布的输入:

gawk -F'\t' '!/^\t/{delete a} !a[$4]++' file

我使用 gawk 所以我可以一次清楚地删除整个数组,而其他 awk 使用不太清楚的:

awk -F'\t' '!/^\t/{split("",a)} !a[$4]++' file
于 2012-11-20T15:47:57.103 回答
0

如果重复的行在所有列中都重复,而不仅仅是第四列,则 uniq(1) 可能是合适的。尝试运行uniq file并查看输出是否符合您的预期。

于 2012-11-19T15:02:01.300 回答