6

我想动态创建一个%detail哈希,而不使用eval语句。此代码与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$'
        };
4

5 回答 5

14

相关部分:

if(my @m = /$regex/) {
  for(my $i=0;$i<=$#$array; $i++) {
      $detail{$array->[$i]} = $m[$i];              
  }   
}   
于 2012-08-29T13:23:30.027 回答
5

更改 for 循环:

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

经过:

@detail{@{$array}} = ($_ =~ $regex);
于 2012-08-29T13:30:15.643 回答
2

如果您可以使用最新版本的 Perl,请参阅(?<name>...)regexp 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$'
        };
于 2012-08-29T14:01:52.227 回答
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];
于 2012-08-29T13:21:48.597 回答
1

使用命名的捕获组,您可以消除%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
于 2012-08-30T01:41:24.517 回答