Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How explicitly resolve variables in a perl string?

Tags:

string

perl

In my perl script I want to have both versions of $config directory:

my $config='$home/client/config';

and

my $config_resolved="$home/client/config";

But I want to get $config_resolved from $config, i.e. something like this:

my $config_resolved=resolve_vars($config);

How can I do such thing in perl?

like image 698
Mihran Hovsepyan Avatar asked Dec 05 '25 20:12

Mihran Hovsepyan


1 Answers

From the Perl FAQ (which every Perl programmer should read at least once):

How can I expand variables in text strings?

(contributed by brian d foy)

If you can avoid it, don't, or if you can use a templating system, such as Text::Template or Template Toolkit, do that instead. You might even be able to get the job done with sprintf or printf:

my $string = sprintf 'Say hello to %s and %s', $foo, $bar;

However, for the one-off simple case where I don't want to pull out a full templating system, I'll use a string that has two Perl scalar variables in it. In this example, I want to expand $foo and $bar to their variable's values:

my $foo = 'Fred';
my $bar = 'Barney';
$string = 'Say hello to $foo and $bar';

One way I can do this involves the substitution operator and a double /e flag. The first /e evaluates $1 on the replacement side and turns it into $foo. The second /e starts with $foo and replaces it with its value. $foo, then, turns into 'Fred', and that's finally what's left in the string:

$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'

The /e will also silently ignore violations of strict, replacing undefined variable names with the empty string. Since I'm using the /e flag (twice even!), I have all of the same security problems I have with eval in its string form. If there's something odd in $foo, perhaps something like @{[ system "rm -rf /" ]}, then I could get myself in trouble.

To get around the security problem, I could also pull the values from a hash instead of evaluating variable names. Using a single /e, I can check the hash to ensure the value exists, and if it doesn't, I can replace the missing value with a marker, in this case ??? to signal that I missed something:

my $string = 'This has $foo and $bar';
my %Replacements = (
    foo  => 'Fred',
    );
# $string =~ s/\$(\w+)/$Replacements{$1}/g;

$string =~ s/\$(\w+)/
            exists $Replacements{$1} ? $Replacements{$1} : '???'
            /eg;
print $string;
like image 113
Dave Cross Avatar answered Dec 08 '25 10:12

Dave Cross