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

Greetings and Salutations most learned Monks,

I petition you today on a matter beyond my novice ability. What I am trying to do may not even be possible, but here goes, see bolded text for the actual question.

As a part of processing, these variables get populated early in the process

$a_test="1"; $b_test="the RTE";
Later in the process, when writing to the logfile, this line of text gets retrieved from a message table and is placed in variable $text

  $text='titl=This is test $ma_test of $mb_test broadcasting system';

Attempting to populate variables in retrieved string with those already defined and populated earlier in the process

$start=1; while (index($text,'$',$start) > 0) { $dsign=index($text,'$',$start); $blank=index($text,' ',$dsign); $w=substr($text,$dsign,($blank-$dsign)); ${(substr($w,1,length($w)-1))}=${(substr($w,2,length($w)-2))}; $start = $blank += 1; print " result: ${(substr($w,1,length($w)-1))}\n"; }
Iteration 1 prints "result: 1"
Iteration 2 prints "result: the RTE"

Values of resolved variables
  print "ma_test: $ma_test\n";
prints out ma_test: 1
  print "mb_test: $mb_test\n";
prints out mb_test: the RTE

Create and populate variable $titl with the remaining text in the string

${(substr($text,0,4))}=substr($text,5,length($text)-5); print " output: $titl\n";
looking for this: This is test 1 of the RTE broadcasting system
Instead get this: This is test $ma_test of $mb_test broadcasting system

Is it possible to resolve the variables in the text string to the values in $ma_test and $mb_test?

Thank you for any consideration

R_D

Replies are listed 'Best First'.
Re: Resolving Imbedded Variables
by davidrw (Prior) on Nov 07, 2005 at 17:41 UTC
    Things like this are a lot easier if the data is in a hash .... they you can just find your keys and replace with the hash value. Also, regex (see perlre, especially for details about the /e modifier)is the way to go here instead of the substr string walking. You may also want to see if something like Template Toolkit will quit your needs/be easy to implement in your case.
    my %data = ( ma_test => 1, mb_test => 'the RTE', ); my $text = 'titl=This is test $ma_test of $mb_test broadcasting system +'; $text =~ s/\$(\w+)/ $data{$1} /g; print $text;
    Alternatively, you might want something like this:
    my %data = ( ma_test => 1, mb_test => 'the RTE', ); my $text = 'titl=This is test $ma_test blah $x of $mb_test broadcastin +g system'; $text =~ s/\$(\w+)/ exists $data{lc $1} ? $data{lc $1} : '==VARIABLE_N +OT_FOUND==' /eg; print $text;
Re: Resolving Imbedded Variables
by sauoq (Abbot) on Nov 07, 2005 at 17:44 UTC

    Here's one way...

    my $string = 'foo: $foo and bar: $bar\n'; print $string, "\n"; my $foo = "foozleberry pie"; my $bar = "barzleberry foo"; print eval 'qq(' . $string . ')';
    In other words, just take your string and eval it as a double quoted string.

    Another technique which is a little less prone to error is to use a hash and perform a substitution on it. In this case, your placeholders only look like perl variables...

    my %vars = ( foo => 'foozleberry pie', bar => 'barzleberry foo', ); my $string = 'foo: $foo and bar: $bar'; $string =~ s/\$(\w+)/$vars{$1}/g; print $string, "\n";

    -sauoq
    "My two cents aren't worth a dime.";
    
      A technique similar to your hash suggestion can make the eval approach secure from code-insertion mischief (I'm guessing this is what you meant by "prone to error"):
      my $string = 'foo: $foo and bar: $bar\n'; print $string, "\n"; my $foo = "foozleberry pie"; my $bar = "barzleberry foo"; $string =~ s/(\$\w+)/$1/gee; print $string, "\n";
      Update: A hash is still a better choice because it automatically restricts which variables will be substituted to a set that you specify, which is almost surely desirable.

      Caution: Contents may have been coded under pressure.
Re: Resolving Imbedded Variables
by Tanktalus (Canon) on Nov 07, 2005 at 22:12 UTC

    As others have pointed out, you need to use a hash to make this reasonable. Instead of putting your replacement values into numerous variables, just put them all in a hash, then you need a way to pull them back out by their name. The way I have done this in production since, oh, about February, is here. Prior to that was a relatively ugly method, but always using hashes. The linked-to node here shows a way to put the replacement algorithm in one function (expand_string) and the actual lookup in another (expand_variable). In that node, I use parenthesis to delimit variables, but you could change that code to use whatever you want.

Re: Resolving Imbedded Variables
by donarb (Beadle) on Nov 07, 2005 at 17:35 UTC
    The problem is that you are using single quotes around your output string. Use double quotes instead:
    $text="titl=This is test $ma_test of $mb_test broadcasting system";
    You should read up on variable interpolation and the different ways of quoting strings.
      I think he's getting that string, sigils and all, out of a database and is really looking for a custom templating solution.
Re: Resolving Imbedded Variables
by pajout (Curate) on Nov 07, 2005 at 17:48 UTC
    Something like as
    perl -e 'my $var = q(VARVALUE); my $out = qq(This is the $var.); print + $out;'
    The point is qq(), which is interpolating, instead of q().
    Update: Please, forgot it, I am too tired now :(