多列文件比较和范围提取

时间:2016-10-31 12:55:17

标签: perl

请原谅我在没有任何编码努力的情况下提问。但对我来说似乎太难了。

我有一个数据文件,其中tab分为三个数据列(以及一些重复的标题行):

Sequence ../Output/yy\Programs\NP_416485.4 alignment. Using default output format...
# ../Output/Split_Seq/NP_415931.4.fasta -- js_divergence - window_size: 3 
# jjhgjg cstr score

0   0.89    u-p
1   -5.79   --- 
2   0.85    yui
3   0.51    uio
4   0.66    -08
Sequence ../Output/yy\Programs\YP_986467.7 alignment. Using default output format...
# ../Output/Split_Seq/YP_986467.7.fasta -- js_divergence - window_size: 3 
# jjhgjg cstr score

0   0.001   -s-
1   0.984   ---
2   0.564   -fg
3   0.897   -sr

从第二个数据列开始,对于那些大于0.5的值,我想提取相应的第一个列号(或范围)。

对于上面的输入,输出将是:

NP_416485.4: 1, 3-5
YP_986467.7: 2-4

这里,“NP_416485.4”和“YP_986467.7”来自头描述符(在\ Programs之后)。 (注意,例如,“NP_416485.4”的实际值应为“NP_416485.4:0,2-4”,但我将所有值都增加为+1,因为我不想以0开头)。

感谢您的考虑。我将不胜感激任何帮助。谢谢

2 个答案:

答案 0 :(得分:1)

你并没有真正对问题做出很好的描述,而你自己也没有做出任何努力来解决问题,但这是解决问题第一部分的方法(解析问题)归档到数据结构中)。您需要遍历%results哈希并生成所需的输出。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Data::Dumper;
my %results;
my $section;

while (<DATA>) {
  # Look for a new section
  if (/\\Programs\\(\S+)\s/) {
    $section = $1;
  }

  # Look for data lines
  if (/^\d\b/) {
     my @data = split;
     if ($data[1] > 0.5) {
       push @{$results{$section}}, $data[0] + 1;
     }
  }
}

say Dumper \%results;

__DATA__
Sequence ../Output/yy\Programs\NP_416485.4 alignment. Using default output format...
# ../Output/Split_Seq/NP_415931.4.fasta -- js_divergence - window_size: 3
# jjhgjg cstr score

0   0.89    u-p
1   -5.79   ---
2   0.85    yui
3   0.51    uio
4   0.66    -08
Sequence ../Output/yy\Programs\YP_986467.7 alignment. Using default output format...
# ../Output/Split_Seq/YP_986467.7.fasta -- js_divergence - window_size: 3
# jjhgjg cstr score

0   0.001   -s-
1   0.984   ---
2   0.564   -fg
3   0.897   -sr

答案 1 :(得分:1)

这是一种方法。如果您在Unix机器上有DOS数据文件,我使用\r?\n来匹配新行,因此它适用于所有情况:

use feature qw(say);
use strict;
use warnings;

my $file_name = 'input.txt';
open ( my $fh, '<', $file_name ) or die "Could not open file '$file_name': $!";
my $str = do { local $/; <$fh> };
close $fh;

my @chunks = $str =~ /(Sequence(?:.(?!Sequence))*)/sg;
my %ids;
for my $cstr ( @chunks ) {
    my ( $id, $data ) = $cstr 
        =~/Split_Seq\/(\S+)\.fasta.*?\r?\n\r?\n(.*)$/s;
    my @lines = split /\n/, $data;
    my @vals;
    for my $line ( @lines ) {
        my @fields = split " ", $line;
        push ( @vals, $fields[0] + 1 ) if $fields[1] > 0.5;
    }
    $ids{$id} = \@vals;
}

for my $id ( keys %ids ) {
    my @tmp = sort { $a <=> $b } @{ $ids{$id} };
    my ( $first, $last );
    my @rr;
    for my $i (0..$#tmp) {
        if ( $i == 0 ) {
            $first = $tmp[0];
            $last = undef;
        }
        if ( $i < $#tmp && ($tmp[$i] == ($tmp[$i+1] - 1 )) ) {
            $last = $tmp[$i+1];
            next;
        }
        if ( defined $last ) {
            push @rr, "$first-$last";
            $last = undef;
        }
        else {
            push @rr, $tmp[$i];
        }
        $first = ( $i < $#tmp ) ? $tmp[$i+1] : undef;
    }
    say "$id: ", join ",", @rr;
}

<强>输出:

NP_416485.4: 1,3-5
YP_986467.7: 2-4