将包含2列的文本文件转换为Perl哈希

时间:2015-10-07 16:06:26

标签: perl text hash

以下是我的INPUT文本文件

StudentName                                       Address
Boris                                             Vietnam
Henry                                             Ukrine
Sarah                                             Road/47
                                                  Turkey
John                                              NewsLand 
                                                  now local
Boris                                             now local
Karen                                             4th/floor
                                                  WestHam/Apartments
                                                  Culverdown/Street
                                                  WestHam
                                                  UK

要将上面的内容转换成哈希,我试过跟随(当然它根本不起作用)

use strict; use warnings; use Data::Dumper;

my $out1 = "Sample.txt"; my %hash;


open FILE1, "<", $out1 or die "$!\n"; 
while ( <FILE1> ) { 
  chomp $_; 
  my ( $name, $address ) = split '\t', $_; 
  $hash{$name} = [$address];
  push @{ $hash{$name} }, $_; 
}

close FILE1;

print "ResultHash".Dumper(\%hash);

有人可以建议如何将上面的文本文件转换为哈希.left列是关键,一个是列。 注意:我从寄存器中获取了所有唯一的键值,因此我可以将它们用作键。然后我需要将这两列转换为values.one将只是studentname标量,其他将作为数组地址。

3 个答案:

答案 0 :(得分:1)

这里的关键问题是正确地跳过重复的名字。一种可能的方法:

my $name;
while ( <FILE1> ) { 
  chomp; 
  my @row = split /\s+/, $_, 2;
  next if $row[0] eq 'StudentName';
  $name = $row[0] unless $row[0] eq '';
  push @{ $hash{$name} }, $row[1];
}

在这里,我使用三个param形式的split来限制块的数量,跳过StudentNamenext,填充$name仅当行以非空白符号。

请注意,由于自动更新,您不必为每个特定记录预先创建列表 - 推送将自动创建相应的数据结构。

答案 1 :(得分:1)

您遇到的问题是您的while循环基于换行符进行迭代。在第一行 - 您有一个学生姓名,但下一行是您没有。

所以我建议你想要做的是:

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

my %addresses;
my $current_student_name;

my $header_line = <>;

while (<>) {
    my $address_line;
    if (m/^\w/) {
        ( $current_student_name, $address_line ) = m/^(\w+)\s*(.*)/;
    }
    else {
        ($address_line) = m/^\s*(.*)/;
    }
    push( @{ $addresses{$current_student_name} }, $address_line );
}

print Dumper \%addresses;

答案 2 :(得分:0)

如果我做对了,这可能是一个解决方案。

my $prev_name;
while ( <FILE1> ) { 
    chomp $_; 
    my ( $name, $address ) = split /\s+/, $_, 2;
    $hash{$prev_name = $name} ||= [] if $name;
    push($hash{$name || $prev_name}, $address);
}