删除最后具有重复值的行



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

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     

我希望应该删除重复列 4 值的行。

前三列是坐标,在这些坐标中列出了我们找到的任何内容(在 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

没有任何效果:(

请帮忙

谢谢

你只需要

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
sed '1{x;d};H;x;s/([ ][^n ]*)[ ]*n[ ]*1[ ]*n/1n/;$p;x;d;$p;x;d' FILE

如果文件中有制表符,除了空格之外,您可以将所有[ ]替换为 [[:space:]]

简单的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/  */ttt/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/  */ttt/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

请注意,现在有一行以 MRTO4 结尾!

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

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

使用一个小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
<</div> div class="one_answers">

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

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

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

awk -F't' '!/^t/{split("",a)} !a[$4]++' file

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

相关内容

  • 没有找到相关文章

最新更新