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

I store data using XML::Simple. I use forcearray so that everything is consistent, and refer to my data as referenced variables. I want to embed a reference in the xml, extract it, and populate it at run time. The variable has to be stored within the string, so it won't get set when the xml file is written.

The usual method doesn't work --

====usual variable substitution idiom for comparison==== my $lamb = 'wolf'; my $text = 'Mary had a little $lamb.'; $text =~ s/(\$\w+) /$1/eeg; print $text;

The solution -- the regex needs an update:

my $lamb; my $mary="Little Rabbit Foo Foo "; $lamb->{data}[0] = 'wolf'; my $text = '$mary had a little $lamb->{data}[0].'; $text =~ s/(\$[\w\-\>\{\}\[\]]+)[ \.]/$1/eeg; print $text;

Is there a cleaner way of writing the regex that doesn't involve extensive tweaking of the data? I'm chafing under the restriction of losing my space or period and having to supply it elsewhere.

Replies are listed 'Best First'.
Re: expanding quoted referenced data
by diotalevi (Canon) on Sep 08, 2006 at 17:56 UTC

    It sounds like you're trying to do $text = eval qq["$text"]. It's not a good idea and neither is what you said you wanted. Try using a real templating module, one that doesn't involve eval or /e.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      It's not a good idea and neither is what you said you wanted.
      Granted.
      It sounds like you're trying to do $text = eval qq["$text"].
      Note: if the OP does decide to use eval() despite all the reasons not to then a heredoc is better than "" as it avoids sensativity to " characters in the data.
      chop ( $text = eval "<<_EOD_$text\n_EOD_" );

      This, of course, is stil confused by "\n_EOD_\n" in the data is still subject to all the dangers implicit in eval().

      Thanks for all the help. Near term, I'll use the eval to eliminate the regex. Long term, I'll learn Text::Template or some such.

      Tyson
Re: expanding quoted referenced data
by shmem (Chancellor) on Sep 08, 2006 at 17:01 UTC
    The usual method doesn't work --
    ====usual variable substitution idiom for comparison==== my $lamb = 'wolf'; my $text = 'Mary had a little $lamb.'; $text =~ s/(\$\w+) /$1/eeg; print $text; # ^------------- ?
    Doesn't work because of the extra blank after your capturing parens.
    $text =~ s/(\$\w+)/$1/eeg; print $text; __END__ Mary had a little wolf.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: expanding quoted referenced data
by philcrow (Priest) on Sep 08, 2006 at 17:02 UTC
    I think it is just the trailing space in the pattern which is tripping you. I tried:
    #!/usr/bin/perl use strict; my $lamb = 'wolf'; my $text = 'Mary had a little $lamb.'; $text =~ s/(\$\w+)/$1/eeg; print $text . "\n"; # output: Mary had a little wolf.
    Phil
Re: expanding quoted referenced data
by Anonymous Monk on Sep 08, 2006 at 17:30 UTC

    Missing the point. The regex has to catch $lamb->{data}[0].

    Catching $lamb is an easy cut 'n paste job. Getting it to catch $lamb->{data}[0] whether or not there is a space or period after, and not losing the referenceness of the reference is the issue.

      my $lamb; $lamb->{data}[0] = 'wolf'; my $mary = "Little Rabbit Foo Foo"; my $template = '$mary had a little $lamb->{data}[0].'; $text = eval qq{"$template"}; print $text;

      You're treading down a dangerous path. Why don't you use an existing template system instead of rolling out your own?

      Ah, ok. Then -
      my $lamb; my $mary="Little Rabbit Foo Foo "; $lamb->{data}[0] = 'wolf'; my $text = '$mary had a little $lamb->{data}[0].'; $text =~ s/(.*)/"\"$1\""/ee; print $text,"\n"; __END__ Little Rabbit Foo Foo had a little wolf.

      but then, there's an extra space between "Foo Foo" and "had", since $mary's got it. Maybe $mary =~s/^\s|\s$/g, then.

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      My bad.

      I keyed on the simpler regex you quoted and didn't try it without the space/period alternates. Thanks for the help.