2017-04-20 29 views
1

我的正則表達式只匹配一些表達式。當我在regex101.com上測試表達式時,它工作得很好......可能是我的代碼存在問題?perl:正則表達式只匹配一些時間

感謝您的幫助提前。

示例文件, 「surfacecoating」:

[ 
('amino acids', 339, 350), 
('copper', 71, 77), 
('copper', 0, 6), 
('copper', 291, 297), 
('amino acids', 119, 130)] 

自卸車打印出這個文件是什麼(請注意前3場比賽不返回):

'surfacecoating' => { 
     'copper' => '291', 
     'amino acids' => '119' 
    }, 

代碼:

#!/usr/bin/perl 

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

determine_cde_instances(); 

sub determine_cde_instances { 
    my %cdeinstances; 
    my %cde_instances; 

    my $dir = "/results/CDE"; 
    opendir my $dh, $dir or die "Can't open $dir: $!"; 

    while (my $file = readdir($dh)) { 
     next if ($file =~ m/^\./); 
     next if -d $file; 

     open my $fh, '<', "$dir/$file" or die "Can't open $dir/$file: $!"; 

     while (my $line = <$fh>) 
     { 
       if (my ($instance) = $line =~ m/'(.*?)', (.*?), /)  
       { 
        my $instance = $1; 
        my $pos = $2; 
        $cde_instances{$file}{$instance} = $pos; 
       } 
     } 
     close $fh; 
    }  
    close $dh; 

    print Dumper(\%cde_instances); 
    return %cde_instances; 
} 
+1

您的數據文件是序列的集合,但是您的代碼會在序列的一個成員上鍵入一個(嵌套的)關聯數組。一個[數組數組](http://perldoc.perl.org/perldsc.html#ARRAYS-OF-ARRAYS)最明顯地代表了數據文件中的結構 - 但是你想在代碼中使用什麼結構?換句話說,你會期望'Dumper'輸出什麼? – pilcrow

+0

您可能會在將每個'cde_instance'覆蓋到'$ cde_instances'的同時覆蓋每個'cde_instance'(它可能需要將第一個匹配作爲關鍵字[只是猜測],這與'('copper',0,6'和'('copper',291,297)'。在$ cde_instances {$ file} {$ instance} = $ pos;' –

回答

2

您正在使用密鑰$instance在hashref中存儲信息,但您的數據中的某些密鑰是相同的多行。所以關鍵'copper'被重複覆蓋,最後只有最後一次發生。 'amino acids'也是如此。

由於這些關鍵字待散列鍵重複,你不能用一個直接的散列。你需要想出一個不同的數據結構,它將取決於你需要用數據做什麼。

合理的想法是使用一個陣列,並且也許與hashrefs陣列,一個用於每一對

if ($line =~ m/'(.*?)', (.*?), /)  
{ 
    my %instance_pos = ($1, $2); 

    push @{$cde_instances{$file}}, \%instance_pos; 
} 

在這裏,在散列%cde_instances每個鍵$file具有數組引用作爲它的值,攜帶爲每個hashrefs實例 - pos對。當然,還有其他選擇,這更多是一個例子。

這也可以寫成

if (my %instance_pos = $line =~ m/'(.*?)', (.*?), /) { 
    push @{$cde_instances{$file}}, \%instance_pos; 
} 

或只是

if ($line =~ m/'(.*?)', (.*?), /) {  
    push @{$cde_instances{$file}}, {$1, $2}; 
} 

如果您需要檢查/驗證捕獲然後從正則表達式分配給兩個變量。


隨着上述變化,並使用use Data::Dump qw(dd);打印我得到

 
{ 
    "data.txt" => [ 
    { "amino acids" => 339 }, 
    { copper => 71 }, 
    { copper => 0 }, 
    { copper => 291 }, 
    { "amino acids" => 119 }, 
    ], 
} 

需要注意的是在後的第一個行號不會被您正則表達式捕獲。我認爲這是爲了達到目的。請澄清它並非如此。

+0

中使用另一個鍵(除'$ instance')你的解釋是有道理的,我看到我出錯的地方;誤解了哈希的一個基本方面。 是的,我只需要保存第一個數字,而不是每行的第二個數字。 再次感謝您! – jelly

+0

@jelly非常好,很高興聽到:)我添加了幾種方法來編寫代碼(可能對您而言不會是新的) – zdim

+0

如何直接訪問%instance_pos的鍵值? (沒有進入循環)像$ cde_instances {$ file} {$ 1} – jelly