Чтение всего файла в хеш в Perl - PullRequest
3 голосов
/ 30 сентября 2011

У меня проблемы с чтением файла в хеш в Perl.

Chr1_supercontig_000000000  1   500
    PILOT21_588_1_3_14602_59349_1
Chr1_supercontig_000000001  5   100
    PILOT21_588_1_21_7318_90709_1
    PILOT21_588_1_43_18803_144592_1
    PILOT21_588_1_67_13829_193943_1
    PILOT21_588_1_42_19678_132419_1
    PILOT21_588_1_67_4757_125247_1
...

Итак, у меня есть этот файл выше.Мой желаемый результат - хеш с линиями "Chr1" в качестве ключа и линиями "PILOT" в качестве значений.

Chr1_supercontig_000000000 => PILOT21_588_1_3_14602_59349_1
Chr1_supercontig_000000001 => PILOT21_588_1_21_7318_90709_1, PILOT21_588_1_43_18803_144592_1,...

Насколько я знаю, несколько значений могут быть назначены клавише только по ссылке, это правильно?

Я застрял в этой точке и мне нужна помощь.

Ответы [ 6 ]

5 голосов
/ 30 сентября 2011

Вы можете прочитать файл построчно, отслеживая текущий хэш-ключ:

open my $fh, '<', 'file' or die $!;

my (%hash, $current_key);

while (<$fh>) {
    chomp;        
    $current_key = $1, next if /^(\S+)/;
    s/^\s+//; # remove leading space
    push @{ $hash{$current_key} }, $_;
}
5 голосов
/ 30 сентября 2011

Вы правы, хеш-значения должны быть ссылками, указывающими на массивы, содержащие строки PILOT.

Вот способ сделать это:

my %hash;
open FILE, "filename.txt" or die $!;
my $key;
while (my $line = <FILE>) {
     chomp($line);
     if ($line !~ /^\s/) {
        ($key) = $line =~ /^\S+/g;
        $hash{$key} = [];
     } else {
        $line =~ s/^\s+//;
        push @{ $hash{$key} }, $line;
     }
 }
 close FILE;
2 голосов
/ 30 сентября 2011

Уже много хороших ответов, поэтому я добавлю один, который не основан на регулярных выражениях, а скорее на том, что ключевые строки содержат три записи с пробелами / табуляцией и значения только один.

Этоавтоматически удалит начальные пробелы и символы новой строки, и это несколько удобно.

use strict;
use warnings;

my %hash;
my $key;

while (<DATA>) {
    my @row = split;
    if (@row > 1) {
        $key = shift @row;
    } else {
        push @{$hash{$key}}, shift @row;
    }
}

use Data::Dumper;
print Dumper \%hash;

__DATA__
Chr1_supercontig_000000000  1   500
    PILOT21_588_1_3_14602_59349_1
Chr1_supercontig_000000001  5   100
    PILOT21_588_1_21_7318_90709_1
    PILOT21_588_1_43_18803_144592_1
    PILOT21_588_1_67_13829_193943_1
    PILOT21_588_1_42_19678_132419_1
    PILOT21_588_1_67_4757_125247_1
2 голосов
/ 30 сентября 2011

Как насчет:

#!/usr/bin/perl 
use strict;
use warnings;
use Data::Dump qw(dump);

my %hash;
my $key;
while(<DATA>) {
    chomp;
    if (/^(Chr1_supercontig_\d+)/) {
        $key = $1;
        $hash{$key} = ();
    } else {
        push @{$hash{$key}}, $_;
    }
}
dump%hash;

__DATA__
Chr1_supercontig_000000000  1   500
    PILOT21_588_1_3_14602_59349_1
Chr1_supercontig_000000001  5   100
    PILOT21_588_1_21_7318_90709_1
    PILOT21_588_1_43_18803_144592_1
    PILOT21_588_1_67_13829_193943_1
    PILOT21_588_1_42_19678_132419_1
    PILOT21_588_1_67_4757_125247_1

Вывод:

(
  "Chr1_supercontig_000000001",
  [
    "    PILOT21_588_1_21_7318_90709_1",
    "    PILOT21_588_1_43_18803_144592_1",
    "    PILOT21_588_1_67_13829_193943_1",
    "    PILOT21_588_1_42_19678_132419_1",
    "    PILOT21_588_1_67_4757_125247_1",
  ],
  "Chr1_supercontig_000000000",
  ["    PILOT21_588_1_3_14602_59349_1"],
)
1 голос
/ 19 мая 2014

Вот еще одна довольно короткая, ясная версия:

while (<>) {
   if(/^Chr\S+/) {
      $c=$&;
   } else {
      /\S+/;
      push @{ $p{$c} }, $&;
   }
}

И для печати результатов:

foreach my $pc ( sort keys %p ) {
   print "$pc => ".join(", ", @{$p{$pc}})."\n";
}

Это более короткие результаты печати (но первый кажется болеедля чтения):

map { print "$_ => ".join(", ", @{$p{$_}})."\n" } sort keys %p;

Однострочная из командной строки:

perl <1 -e 'while(<>){ if(/^Chr\S+/){ $c=$&; }else{ /\S+/; push(@{$p{$c}},$&);} } map { print "$_ => ".join(", ", @{$p{$_}})."\n" } sort keys %p;'
0 голосов
/ 30 сентября 2011

Попробуйте,

#!/usr/bin/perl 
use strict;
use warnings;
use Data::Dumper;

my ( $fh,$cur );
my $hash = ();
open $fh,'<' , 'file' or die "Can not open file\n";

while (<$fh> ) {
    chomp;
    if ( /^(Chr.+? ).+/ ) {
        $cur = $1;
        $hash->{$cur} = '';
    }
    else {
        $hash->{$cur} = $hash->{$cur} .$_ . ',';
    }
}

print Dumper $ hash;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...