emilford has asked for the wisdom of the Perl Monks concerning the following question:

I have lines in a file that can contain dynamic variables in the form ${var_name}. In another file, the dynamic variables are defined as var_name = var_value. I created a hash, such that the key is var_name and the value is var_value. Everything on the left side of the '=" sign is converted to lowercase before being used as a key for consistency.

My question is, what is the best way to find all dynamic variables in a line and swap them with their respective value. I have it currently as a two step problem, but the second, and probably easy part, is giving me issues.
$line =~ s/\$\{\S+\}/\l$1/g; # not sure if escaping the {'s is neces +sary.
Now I can say what I need to do in English, but after a long week, my brain won't give me the Perl code. I need to take $1 and use it in $dynamic_variables{$1} to replace the lefthand side of the s///.

20040414 Edit by BazB: Changed title from 'swapping "dynamic" variables'

Replies are listed 'Best First'.
Re: replacing "dynamic" variables
by bbfu (Curate) on Apr 09, 2004 at 22:00 UTC

    Update2: Also, you might want to look into one of the various Config or templating modules (such as Template-Toolkit), as it sounds like you might be trying to roll your own basic templating system.

    $line =~ s[ \$ # Dollar sign (literal) { # Open brace (literal) ( # capture (into $1) [^}]+ # One or more non-close brace characters ) # end capture } # Close brace (literal) ][$dynamic_variables{$1}]xg;

    Update: Expanded regexp with /x

    bbfu
    Black flowers blossom
    Fearless on my breath

Re: replacing "dynamic" variables
by nothingmuch (Priest) on Apr 10, 2004 at 01:14 UTC
    bbfu's answer is what you want, but you might also be interested in the /e modifier to the substitution op.

    s/(\${\w+})/find_value_for_var("$1")/e

    The above code will find alphaneumerical sequences enclosed in ${}, and then send them to the find_value_for_var() function. Perhaps a more coherent example is

    s/(\d+)/$1 + 5/e;

    Which will find a sequence of digits, then construct the perl expression for those digits, then an addition operator, and then a five, and then evaluate this code, returning the number that was matched plus five.

    -nuffin
    zz zZ Z Z #!perl

      Don't enclose variables in doublequotes!

      s/(\${\w+})/find_value_for_var("$1")/e is better written as s/(\${\w+})/find_value_for_var($1)/e! While in this case the quotes cannot "break" the script, it forces Perl to make an additional copy of the matched string each time the regexp matches.

      I wish "$var" trigered a warning. While I admit there are valid reasons to do that I bet they make up at most 0.01% of the times it's used. :-(

      Jenda
      Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
         -- Rick Osborne

      Edit by castaway: Closed small tag in signature