从文件中提取所需的行并写入另一个

时间:2017-07-10 12:12:48

标签: perl

我有一个带有以下数据的制表符分隔文件。第一列表示ID,第二列是该ID的值。

294535  k__Bacteria  
294535  p__Firmicutes  
294535  c__Clostridia  
294535  o__Clostridiales  
294535  f__Lachnospiraceae  
537364  k__Bacteria  
537364  p__Planctomycetes  
537364  c__vadinHA49  
7652    k__Bacteria  
7652    p__Proteobacteria  
7652    c__Gammaproteobacteria   
7652    o__Thiotrichales  
7652    f__Thiotrichaceae  
7652    g__Leucothrix  
520836  k__Bacteria  
520836  p__Firmicutes  
520836  c__Clostridia  
520836  o__Clostridiales  
520836  f__Lachnospiraceae  
320231  k__Bacteria  

我希望以下列格式输出,即只有具有相同ID的多个项目中的最后两项。

294535  o__Clostridiales  
294535  f__Lachnospiraceae  
537364  p__Planctomycetes  
537364  c__vadinHA49  
7652    f__Thiotrichaceae  
7652    g__Leucothrix  
520836  o__Clostridiales  
520836  f__Lachnospiraceae  

任何人都可以帮我找到一个好的解决方案吗?

我尝试逐行读取文件时使用索引和for循环,但它没有发生。这是我的循环结构,下面没有工作。

while ( <TEMPIN> ) {

    chomp;
    my ($ID, $tax) = split('\t', $_);
    push (@taxID, $ID);
    push (@taxa, $tax);

    for ( $i, $i <= $#taxID, $i++ ) {

        if ( $taxID[$i] = $taxID[$i+1] ) {
            next unless $taxID[$i] != $taxID[$i+1];
        }
        else {
            print "$taxID[$i]\t$taxa[$i]\t$taxID[$i-1]\t$taxa[$i-1]\n";
        }
    }
}

1 个答案:

答案 0 :(得分:2)

这会按照你的要求行事。它为散列%data中的每个ID保留所有值的列表,并在@ids中保持ID的原始出现顺序以防重要

输出循环只是修剪除了每个条目的最后两个项目之外的所有项目并打印它们

程序需要输入文件的路径作为命令行参数,并将输出打印到STDOUT

use strict;
use warnings 'all';

my ( %data, @ids );

while ( <> ) {

    next unless /\S/;
    my ( $id, $val ) = split;

    push @ids, $id unless $data{$id};
    push @{ $data{$id} }, $val;
}

for my $id ( @ids ) {

    my $vals = $data{$id};
    splice @{$vals}, 0, -2;
    print "$id\t$_\n" for @{$vals};
}

输出

294535  o__Clostridiales
294535  f__Lachnospiraceae
537364  p__Planctomycetes
537364  c__vadinHA49
7652    f__Thiotrichaceae
7652    g__Leucothrix
520836  o__Clostridiales
520836  f__Lachnospiraceae
320231  k__Bacteria