Regex 在Perl脚本中创建哈希的步骤

Regex 在Perl脚本中创建哈希的步骤,regex,perl,file,hash,Regex,Perl,File,Hash,创建下面散列的方法是我的文件的内容,当我打开包含下面内容的输入文件时,我们希望从表中grep一些数据,以便创建下面模式的散列 { 'Golden' => { 'PT' => 80, 'po' => 43, 'DFF' => 139145, 'DLAT' => 276,

创建下面散列的方法是我的文件的内容,当我打开包含下面内容的输入文件时,我们希望从表中grep一些数据,以便创建下面模式的散列

{
      'Golden' => {
                      'PT' => 80,
                      'po' => 43,
                      'DFF' => 139145,
                      'DLAT' => 276,
                      'Z' => 4,
                      'BBOX' => 833,
                      'Total' => 140387
                    },
      'Foo Bar' => {
                      'PT' => 80,
                      'po' => 43,
                      'DFF' => 139145,
                      'DLAT' => 276,
                      'Z' => 4,
                      'BBOX' => 833,
                      'Total' => 140387
                   }
    };
文件内容

样本1

 Mapped points: SYSTEM class
 Mapped points     PI     PO     BBOX      Total   
 Golden            86     43     833       140387  
 Revised           86     43     833       140387  
样本2

 Mapped points: SYSTEM class
 Mapped points     PI     PO     DFF    DLAT   Z      BBOX      Total   
 Golden            86     43     139145 276    4      833       140387  
 Revised           86     43     139145 276    4      833       140387  
她就是我被困的地方

if ($line =~ m/^Mapped points: SYSTEM class$/){
    $var = "golden_mapped-points_PI";
    $hash{$var} = $6;
    next unless $line = <$filehandle> and $line =~ /^Mapped points     PI     PO     DFF    DLAT   Z      BBOX      Total   $/; 
}
if($line=~m/^映射点:系统类$/){
$var=“golden\u-points\u PI”;
$hash{$var}=$6;
下一步,除非$line=和$line=~/^映射点PI PO DFF DLAT Z BBOX总计$/;
}

此外,在不同的输入文件编号列中可能会发生变化,例如,它可能只有PI和PO。在这种情况下,我也不知道如何处理输入文件。

我仔细考虑并找到了解决方案!!我知道这不是最好的解决方案,我请求你为我提供最好的解决方案

cat > test.pl
#!/usr/bin/perl  

use strict;
use warnings;

while(<DATA>){
my $line = $_;
if ($line =~ m/^Mapped points: SYSTEM class$/){
    next unless $line = <DATA> and $line =~ /^Mapped points/; 
    my @arr = split(' ',$line);

    next unless $line = <DATA>;

    my @golden_arr = split(' ',$line);
    my $size1 = @golden_arr;
    for(my $i = 1;$i < $size1 ;$i++){
        my $var = "Golden_".$arr[$i+1];
        print "$var, $golden_arr[$i]\n";
    }
    next unless $line = <DATA>;
    my @revised_arr = split(' ',$line);
    my $size2 = @revised_arr;
    for(my $i = 1;$i < $size2 ;$i++){
        my $var = "Revised_".$arr[$i+1];
        print "$var, $revised_arr[$i]\n";
    }   
}
}


__DATA__

Mapped points: SYSTEM class
Mapped points     PI     PO     DFF    DLAT   Z      BBOX      Total   
Golden            86     43     139145 276    4      833       140387  
Revised           86     43     139145 276    4      833       140387  

perl test.pl
Golden_PI, 86
Golden_PO, 43
Golden_DFF, 139145
Golden_DLAT, 276
Golden_Z, 4
Golden_BBOX, 833
Golden_Total, 140387
Revised_PI, 86
Revised_PO, 43
Revised_DFF, 139145
Revised_DLAT, 276
Revised_Z, 4
Revised_BBOX, 833
Revised_Total, 140387
cat>test.pl
#!/usr/bin/perl
严格使用;
使用警告;
while(){
我的$line=$\ux;
如果($line=~m/^映射点:系统类$/){
下一步,除非$line=和$line=~/^映射点/;
my@arr=分割(“”,$line);
下一步,除非$line=;
我的@golden_arr=分割(“”,$line);
我的$size1=@golden_arr;
对于(我的$i=1;$i<$size1;$i++){
我的$var=“Golden”..$arr[$i+1];
打印“$var,$golden_arr[$i]\n”;
}
下一步,除非$line=;
my@Revisited_arr=拆分(“”,$line);
my$size2=@REVIDED_arr;
对于(我的$i=1;$i<$size2;$i++){
我的$var=“修订”..$arr[$i+1];
打印“$var$revisited\u arr[$i]\n”;
}   
}
}
__资料__
映射点:系统类
映射点PI PO DFF DLAT Z BBOX总计
黄金86 43 139145 276 4 833 140387
修订86 43 139145 276 4 833 140387
perl test.pl
金玉皮,86岁
金乌坡,43岁
戈尔登迪福,139145
金杜德拉特,276
戈尔登兹,4
金盒子,833
Golden_总计,140387
修订版_PI,86
经修订的_PO,43
修订版(英国)DFF,139145
修订版,第276页
修订版(四)
修订版_BBOX,833
修订总数,140387

有更好的解决方案吗?

您需要保留标题行的副本,因为标题是内部哈希项的键。一旦开始处理数据行,就需要将第一个项作为外部散列项的键(行的一种标签)移开。一旦这些信息被存储起来,你的标题和数据就会“排成一行”

#/usr/bin/env perl
使用v5.12;
使用数据::转储程序;
my$start_re='映射点:系统类';
我的$headers_re='Mapped\s+points\s+';
我的%u散列;
#找到起跑线
while(){last if/$starting_re/}
#读一行。希望它是标题行
#把它分成几块,然后储存起来,供以后使用
我的@标题;
我的$headers_line=;
如果($headers\u line=~/$headers\u re(.*)/x){
@标题=拆分“”,1美元;
}
否则{
说“不明白标题行。”;
出口1;
}
#处理剩余的每一行
而(){
#拆分数据行并移开
#用作线条标签的第一块
my@data=split“”,$;
my$label=shift@data;
#初始化新的内部哈希和索引变量
我的%inner_哈希=();
我的$index=0;
#迭代构建散列的数据段
for(@data){
$internal_hash{$headers[$index]}=$\u;
$index++;
}
#或者,使用散列切片构建它
#@internal_hash{@headers}=@data;
#通过在外部哈希中创建一个条目
#引用我们的内部散列
$outer\u hash{$label}=\%inner\u hash;
}
说出转储程序(\%outer\u散列);
出口0;

我想出了一个使用unpack的解决方案。它处理不同文件中任意数量的列

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

my %data;

my ($len, @hdrs);
my (@lengths, $template);

while (<DATA>) {
    next if 1 .. /^Mapped points:/;

    s/\s+$//; # safe 'chomp' (if there are spaces at end of string)

    if (s/^(Mapped points\s+)//) {
        $len = length $1;
        @hdrs = split;

        # lengths of all but the last (Total) field
        @lengths = map {length} /(\S+\s+)/g;

        # add 'A*' at the end to capture the 'Total' field
        $template = join("", "A$len", map {'A'. $_} @lengths) . "A*";
    }
    else {

        my ($key, @rest) = unpack $template;

        my %temp;
        @temp{ @hdrs } = @rest;
        $data{$key} = \%temp;
    }   
}
use Data::Dumper; print Dumper \%data;

__DATA__
Mapped points: SYSTEM class
Mapped points     PI     PO     DFF    DLAT   Z      BBOX      Total
Golden            86     43     139145 276    4      833       140387
Revised           86     43     139145 276    4      833       140387
你需要创建一个新的模型,并澄清你的问题。
#!/usr/bin/perl
use strict;
use warnings;

my %data;

my ($len, @hdrs);
my (@lengths, $template);

while (<DATA>) {
    next if 1 .. /^Mapped points:/;

    s/\s+$//; # safe 'chomp' (if there are spaces at end of string)

    if (s/^(Mapped points\s+)//) {
        $len = length $1;
        @hdrs = split;

        # lengths of all but the last (Total) field
        @lengths = map {length} /(\S+\s+)/g;

        # add 'A*' at the end to capture the 'Total' field
        $template = join("", "A$len", map {'A'. $_} @lengths) . "A*";
    }
    else {

        my ($key, @rest) = unpack $template;

        my %temp;
        @temp{ @hdrs } = @rest;
        $data{$key} = \%temp;
    }   
}
use Data::Dumper; print Dumper \%data;

__DATA__
Mapped points: SYSTEM class
Mapped points     PI     PO     DFF    DLAT   Z      BBOX      Total
Golden            86     43     139145 276    4      833       140387
Revised           86     43     139145 276    4      833       140387
$VAR1 = {
          'Golden' => {
                        'Total' => '140387',
                        'BBOX' => '833',
                        'Z' => '4',
                        'PO' => '43',
                        'DLAT' => '276',
                        'DFF' => '139145',
                        'PI' => '86'
                      },
          'Revised' => {
                         'Total' => '140387',
                         'BBOX' => '833',
                         'Z' => '4',
                         'PO' => '43',
                         'DLAT' => '276',
                         'DFF' => '139145',
                         'PI' => '86'
                       }
        };