2012-08-29 29 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(my $i=0;$i<=$#$array; $i++) { 
    $j=$i+1; 
    eval '$detail{$array->[$i]} = $$j'; 
} 

द्वारा:

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

आप दो सरणियों का उपयोग कर सकते @LAST_MATCH_START और @LAST_MATCH_END (perldoc 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

आप पर्ल के नवीनतम संस्करण का उपयोग कर सकते हैं, तो इस नोटेशन को देखेंregexp में 10 perlre docs यह तो $ 1, $ 2, $ 3 आदि

का उपयोग कर अधिक स्पष्ट है स्क्रिप्ट

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

आउटपुट

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

यदि वह नामित मैचों का उपयोग करने जा रहा है तो उसे मैप किए गए सरणी की आवश्यकता नहीं होनी चाहिए, केवल $ @detail {keys% +} = मान% + अगर $ इनपुट = ~ एम {$ regex}; 'या यहां तक ​​कि'% detail =% + $ इनपुट = ~ एम {$ regex}; '। फिर आप रेगेक्स को ऐसी संरचना में डाल सकते हैं जो पुनरावृत्ति के लिए अधिक उपयुक्त है, एक सूची/सरणी। जो मैंने सुझाया होगा उसके लिए +1। – Axeman

+0

'% विस्तार =% + अगर $ इनपुट = ~ एम {$ regex}; 'काम नहीं करेगा, यह पहले से ही'% विस्तार' में क्या फेंकता है। –

1

named capture groups का उपयोग करके आप %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 

यदि आप एक में अपने 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 
संबंधित मुद्दे