2012-08-29 8 views
6

evalステートメントを使用せずに、%detailハッシュを動的に作成したいとします。 このコードはevalステートメントで正常に動作しますが、evalを使用せずにこれを実行するより良い方法はありますか?

my @input=('INFO: Vikram 32 2012','SAL: 12000$','ADDRESS: 54, junk, JUNK'); 

my %matching_hash= (
        qr/^INFO:\s*(\S+)\s+(\S+)\s+(\S+)/ =>['name','age','joining'], 
        qr/^SAL:\s*(\S+)/ => ['salary'], 
        qr/ADDRESS:\s*(.*)/ =>['address'] 
        ); 
my %detail; 
while(my ($regex, $array) = each(%matching_hash)) { 
    foreach (@input){ 
     if(/$regex/) { 
      for(my $i=0;$i<=$#$array; $i++) { 
       $j=$i+1; 
       eval '$detail{$array->[$i]} = $$j'; 
      } 
     } 
    } 
} 
use Data::Dumper; 

print Dumper(\%detail); 
++++++++++++++ 

$VAR1 = { 
      'name' => 'Vikram', 
      'address' => '54, junk, JUNK', 
      'age' => '32', 
      'joining' => '2012', 
      'salary' => '12000$' 
     }; 
+0

私はあなたのevalステートメントが '厳しい'を使っていると、私は思っていません(希望の出力を得るためにテストから削除しなければなりませんでした)。 –

答えて

5

変更forループ:

for(my $i=0;$i<=$#$array; $i++) { 
    $j=$i+1; 
    eval '$detail{$array->[$i]} = $$j'; 
} 

によって:あなたはPerlのの最新のバージョンを使用することができる場合

@detail{@{$array}} = ($_ =~ $regex); 
1

次の2つのアレイを使用することができます@LAST_MATCH_START@LAST_MATCH_ENDperldoc perlvarを参照)一緒にsubstrの代わり$1, $2...と。

$detail{ $array->[$i] } = substr $_, $LAST_MATCH_START[$j], $LAST_MATCH_END[$j] - $LAST_MATCH_START[$j]; 
+0

「英語」以外は同意します。 – hobbs

14

関連部分に似た何か:

if(my @m = /$regex/) { 
    for(my $i=0;$i<=$#$array; $i++) { 
     $detail{$array->[$i]} = $m[$i];    
    } 
} 
2

、この表記を参照してくださいそれはnamed capture groupsを使用し

SCRIPT

use v5.14; 
use Data::Dumper; 

my @inputs = ('INFO: Vikram 32 2012', 'SAL: 12000$','ADDRESS: 54, junk, JUNK'); 

my %matching_hash= (
    qr/^INFO:\s*(?<name>\S+)\s+(?<age>\S+)\s+(?<joining>\S+)/ => [ 'name', 'age', 'joining' ], 
    qr/^SAL:\s*(?<salary>\S+)/        => [ 'salary' ], 
    qr/ADDRESS:\s*(?<address>.*)/        => [ 'address' ], 
); 

my %detail; 
while (my ($regex, $array) = each %matching_hash) { 

    INPUT: 
    foreach my $input (@inputs) { 

     next INPUT if not $input =~ m{$regex}; 

     for my $name (@$array) { 
      $detail{$name} = $+{$name}; 
     } 
    } 
} 

say Dumper(\%detail); 

OUTPUT

$VAR1 = { 
      'name' => 'Vikram', 
      'address' => '54, junk, JUNK', 
      'age'  => '32', 
      'joining' => '2012', 
      'salary' => '12000$' 
     }; 
+2

$ input =〜m {$ regex}の場合は '@detail {keys%+} = values%+'、 '%detail =%+ if 'ならば名前付きマッチを使用する場合はマップされた配列は必要ありません$ input =〜m {$ regex}; '。次に、正規表現をリストア/配列の繰り返しに適した構造に置くことができます。私は何を提案したのでしょうか? – Axeman

+0

'%detail =%+ $ input =〜m {$ regex};'がうまくいかない場合は、すでに '%detail'にあるものを捨てます。 –

1

など$ 1、$ 2、$ 3を使用して、より明らかだ正規表現で10 perlre docs、あなたは%matching_hashの必要性を排除することができますハッシュにする同時に、数値変数を使用する必要性を排除したり、配列内の一致の結果を割り当てることもできます。これは、関連情報を%+に保存するためです。

use 5.10.1; 

my @match = (
    qr'^INFO:\s*(?<name>\S+)\s+(?<age>\S+)\s+(?<joining>\S+)', 
    qr'^SAL:\s*(?<salary>\S+)', 
    qr'ADDRESS:\s*(?<address>.*)', 
); 

sub get_details{ 
    my %detail; 

    for my $input (@_) { 
    for my $match (@match){ 
     next unless $input =~ $match; 
     @detail{keys %+} = values %+; 
     last; 
    } 
    } 

    return \%detail; 
} 

use Data::Dumper; 
my @inputs = ('INFO: Vikram 32 2012', 'SAL: 12000$','ADDRESS: 54, junk, JUNK'); 
say Dumper get_details @inputs 

使用すると、1つにあなたのqr年代を組み合わせた場合、それがさらに簡単に得ることができます。

use 5.10.1; 

my $match= qr" 
    ^INFO: \s* (?<name>\S+) \s+ (?<age>\S+) \s+ (?<joining>\S+) 
    | ^SAL: \s* (?<salary>\S+) 
    | ADDRESS: \s* (?<address>.*) 
"x; 

sub get_details{ 
    my %detail; 

    for my $input (@_) { 
    $input =~ $match; 
    @detail{keys %+} = values %+; 
    } 

    return \%detail; 
} 

use Data::Dumper; 
my @inputs = ('INFO: Vikram 32 2012', 'SAL: 12000$','ADDRESS: 54, junk, JUNK'); 
say Dumper get_details @inputs 
関連する問題