emo3
emo3

Reputation: 1

Problems with Perl eval

I have the following code, which will set the value of $mystring by reading from a file.

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;

my $mystring1 = "vault.\$_[0].org/\$_[1].\$_[2]/os/\$_[4]";
my $mystring2 = "vault.$_[0].org/$_[1].$_[2]/os/$_[4]";

&myfunc ("A1", "b2", "C3", "d4");

sub myfunc {

    print Dumper(\@_);

    print ("Before=$mystring1\n");
    my $test = eval($mystring1);
    print ("test=$test\n");

    print ("Before=$mystring2\n");
    $test = eval($mystring2);
    print ("test=$test\n");
}

However, the following output is produced:

Use of uninitialized value $_[0] in concatenation (.) or string at ./t.pl line 7.
Use of uninitialized value in concatenation (.) or string at ./t.pl line 7.
Use of uninitialized value in concatenation (.) or string at ./t.pl line 7.
Use of uninitialized value in concatenation (.) or string at ./t.pl line 7.
$VAR1 = [
          'A1',
          'b2',
          'C3',
          'd4'
        ];
Before=vault.$_[0].org/$_[1].$_[2]/os/$_[4]
Use of uninitialized value $test in concatenation (.) or string at ./t.pl line 15.
test=
Before=vault..org/./os/
Use of uninitialized value $test in concatenation (.) or string at ./t.pl line 18.
test=

What is causing the issues and how can I achieve the following?

test=vault.A1.org/b2.C3/os/d4

How would I use eval or create a subroutine to get this to work?

Upvotes: 0

Views: 294

Answers (2)

perreal
perreal

Reputation: 97918

You are not using eval correctly. It tries to execute some statement, like vault.., which results in an error (inspect $@ after eval).

This works as expected, because the quotes make it evaluate as a string:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my $mystring1 = '"vault.$_[0].org/$_[1].$_[2]/os/$_[3]"';

&myfunc("A1", "b2", "C3", "d4");

sub myfunc {
    print Dumper(\@_);
    print("Before=$mystring1\n");
    my $test = eval($mystring1);
    print("test=$test\n");
}

But using eval [for this particular task] doesn't make any sense.

Upvotes: 0

Hayden
Hayden

Reputation: 2808

I would not use eval. In general it should be avoided unless absolutely necessary due to the security implications linked to it. In your case it's probably a bad idea as you say

The value of mystring is set in a file being read in

Which means that your eval call could execute arbitrary user input... a bad idea!

Use sprintf instead:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my $mystring1="vault.%s.org/%s.%s/os/%s";

myfunc ("A1", "b2", "C3", "d4");

sub myfunc {
    print Dumper(\@_);
    my $test = sprintf $mystring1, @_;
    print ("test=$test\n");
}

A simple solution that does everything you require.

Upvotes: 5

Related Questions