2012-08-29 22 views
6

ile karma değerini dinamik olarak atamak karma değerini dinamik olarak eval bildirimi kullanmadan oluşturmak istiyorum. Bu kod eval bildirimi ile düzgün çalışıyor, ancak eval kullanmadan bunu gerçekleştirmek için daha iyi bir yolu var mı?

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

Sana 'strict' kullanırsanız sizin eval deyimi (ı istenen çıktıyı almak için benim testin çıkarmak için vardı) çalışacak sanmıyorum. –

cevap

5

Değişim döngüsü için:

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

tarafından: Eğer Perl en son sürümünü kullanabiliyorsa

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

İki diziler kullanabilirsiniz @LAST_MATCH_START ve @LAST_MATCH_END (perldoc perlvar bakınız) birlikte substr yerine $1, $2... ile.

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

"İngilizce" haricinde kabul edildi. – hobbs

14

İlgili bölüm benzer bir şey:

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

, bu nota bakınregexp 10 perlre docs Bu named capture groups kullanma

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); 

ÇIKIŞ

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

Eşleştirilmiş dizileri kullanacaksa eşlemeli dizilere gerek olmamalıdır sadece '@detail {keys% +} = değerler% + eğer $ input = ~ m {$ regex}; veya hatta'% detail =% + eğer $ input = ~ m {$ regex}; '. Sonra regex'leri yineleme, bir liste/dizi için çok daha uygun bir yapıya koyabilirsiniz. Öneririm için +1. – Axeman

+0

'% detay =% + $ input = ~ m {$ regex};' 'işe yaramazsa, '% detail' içinde olanı atar. –

1

, sen %matching_hash ihtiyacını ortadan kaldırabilir sonra $ 1, $ 2, $ 3 vb

kullanarak SCRIPT daha net bir karma olmak. Aynı zamanda sayı değişkenlerini kullanma ihtiyacını ortadan kaldırarak veya bir dizinin sonucunu bir dizide atayarak. Bunun nedeni, ilgili bilgileri %+ içine saklayacaktır.

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 

Eğer biri halinde qr 's birleştirirseniz Hatta daha basit alabilirsiniz.

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