How to dynamically assign a hash with $ 1, $ 2, $ 3

I want to dynamically create a %detail hash without using the eval operator. This code works fine with the eval operator, but is there a better way to accomplish this without using 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$' }; 
+6
source share
5 answers

Change the for loop:

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

by:

 @detail{@{$array}} = ($_ =~ $regex); 
+5
source

Relevant Part:

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

If you can use the latest version of Perl, see this notation (?<name>...) in regexp perlre docs. This is more understandable if you use $ 1, $ 2, $ 3, etc.

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
source

You can use two arrays @LAST_MATCH_START and @LAST_MATCH_END (see perldoc perlvar ) along with substr instead of $1, $2... Something like

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

Using the named capture groups , you can eliminate the need for %matching_hash to hash. At the same time, eliminating the need to use numeric variables or assigning the result of a match in an array. This is due to the fact that it will save the relevant information in %+ .

 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 

It can become even easier if you combine your qr into one.

 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 
+1
source

Source: https://habr.com/ru/post/924071/


All Articles