I imagine you are in a refactoring scenario where you already have a big chunk of code which uses global variables like @arr_0 and you want to incorporate (i.e. copy-paste) it into a new script to work with data from front end but without converting that said chunk of code into a function for which all those global params should be function params.
In my imagination, one way forward would be to convert your "chunk of code" to a function and pass its params either as one-after-the-other or as one single monolithic hash: the front-end hash you mentioned with all empty-items filtered out. It's trivial to filter out empty values :
use strict;
use warnings;
my %h = ('a'=>'123','b'=>'xxx','c'=>'');
my %newhash;
for(keys %h){ $newhash{$_} = $h{$_} if $h{$_} ne '' };
print join(",", keys %newhash)."\n";
After the intro. This declares the keys of the hash as variables and initialises them to whatever value they have in the hash and they are accessible in the outer scope:
use strict;
use warnings;
my %h = (
'a' => 'aaa',
'b' => ''
);
for(keys %h){
next if $h{$_} eq '';
my $evalstr = "\$$_ = '$h{$_}';";
print "eval: $evalstr\n";
eval $evalstr;
die "eval $@" if $@;
}
print "a=$a\n";
HOWEVER, $a is a pre-declared variable in Perl and the above code compiles OK (though strict should have complained because we are using a variable at print "a=$a\n"; without declaring it at compile time but only through an eval() at runtime.
There is an added complexity: in your scenario your real variables are completely unrelated to the front-end hash keys. So you will probably need a hash giving the correspondence between front-end variables and real variables.
This can work for you if you are willing to not use use strict;
#!/usr/bin/env perl
#use strict;
use warnings;
my %params = (
'default-0' => ['lakja', 'haljl', 'alka'],
'default-1' => 'abc',
'default-2' => [1, 54, 83, 23],
'default-3' => [],
'default-4' => '',
'default-5' => '2019-06-26 00:00:10',
);
my %cor = (
'default-0' => '@arr_0',
'default-1' => '$scal_1',
'default-2' => '@arr_2',
'default-3' => '@arr_3',
'default-4' => '$scal_4',
'default-5' => '$date_5',
# etc
);
my $evalstr;
for(keys %params){
my $varname = $cor{$_};
die "var not found for $_" unless defined $varname;
if( $varname =~ /^\$/ ){
next if $params{$_} eq '';
# quote value because it's a string: very basic rule of thumb.
+..
$evalstr = "$varname = '$params{$_}';";
} elsif( $varname =~ /^@/ ){
next if @{$params{$_}}==0;
$evalstr = "$varname = ".'@{["'.join('","',@{$params{$_}}).'"]
+};';
} else { die "can't handle $varname = ".$params{$_} }
print "eval: $evalstr\n";
eval $evalstr;
die "eval $@" if $@;
}
print '@arr_0='."@arr_0\n".'$scal_1='."$scal_1\n";
prints:
Possible unintended interpolation of @arr_0 in string at b.pl line 45.
Name "main::arr_0" used only once: possible typo at b.pl line 45.
Name "main::scal_1" used only once: possible typo at b.pl line 45.
eval: @arr_0 = @{["lakja","haljl","alka"]};
eval: $date_5 = '2019-06-26 00:00:10';
eval: @arr_2 = @{["1","54","83","23"]};
eval: $scal_1 = 'abc';
@arr_0=lakja haljl alka
$scal_1=abc
IMO: the whole idea though is flawed. It is roguelike to use the word of the day.
bw, bliako |