Perl passes argument to eval

I ran into a problem using the eval function.

Indeed, I have some kind of function name inside the SQL database, my goal is to execute these functions in perl (after extraction in SQL).

Here's what I do, given that $ RssSource β†’ {$ k} {Proceed} contains "& test" as a string derived from SQL:

my $str2 = "ABCD"; eval "$RssSource->{$k}{Proceed}";warn if $@ ; sub test { my $arg = shift; print "fct TEST -> ", $row, "\n"; } 

This works correctly and displays:

 fct TEST -> 

However, I would like to be able to pass $ str2 as an argument to $ RssSource β†’ {$ k} {Proceed}, but I don’t know how every syntax I tried returned an error:

 eval "$RssSource->{$k}{Proceed}$str2" eval "$RssSource->{$k}{Proceed}($str2)" eval "$RssSource->{$k}{Proceed}"$str2 eval "$RssSource->{$k}{Proceed}"($str2) 

Can someone tell me how to pass the argument of the evaluated function correctly?

Many thanks for your help

Sincerely.

Florent

+4
source share
5 answers

I assume that $RssSource->{$k}{Proceed} always contains name or &name , otherwise what you ask for does not make much sense.

 my $func_name = $RssSource->{$k}{Proceed}; $func_name =~ s/&//; my $func_ref = \&$func_name; # Works with strict on! $func_ref->(@args); 

If you want to add some error checking, the following will check if sub can be called:

 defined(&$func_ref) 
+5
source

If the eval ing string is always an auxiliary call, you can build the eval string in one of the following ways:

 $RssSource->{$k}{Proceed} . '($str2)' 

(most common), or

 $RssSource->{$k}{Proceed} . "(\"$str2\")" 

(tasteless)

Here are the problems your solutions ran into:

eval "$RssSource->{$k}{Proceed}$str2" evaluates to eval "&testABCD" . This sub does not exist.

eval "$RssSource->{$k}{Proceed}($str2)" evaluates to "&test(ABCD)" . Invalid value.

eval "$RssSource->{$k}{Proceed}"$str2 A string must be followed by some operator, not another variable.

eval "$RssSource->{$k}{Proceed}"($str2) You are trying to call a string as a function. This is not supported in Perl.

+3
source

If you can change the data in your database so that it contains only the name of the function, that is, test , and not &test , you can call the function using a symbolic link, rather than using eval:

 $fn="test"; &{$fn}("argument") 
+2
source

You do not need eval if, as you say, your database just contains function names. You can use them as symbolic links (but please remove &). The modern way to do this is not to use and dereference it, but to use the arrow operator:

 { no strict 'refs'; # hopefully you have strict on already... $RssSource->{$k}{Proceed}->($str2); } 
+1
source

The answer is very similar to ikegami, using the can method, which I like more. TIMTOWTDI.

 my $func_name = $RssSource->{$k}{Proceed}; $func_name =~ s/&//; my $func_ref = __PACKAGE__->can($func_name) or die "No function named $func_name"; $func_ref->(@args); 
0
source

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


All Articles