wuwuwu
wuwuwu

Reputation: 95

Perl: Can I store backreferences (not their values) in variables?

I'd like to do something like this:

my $text = "The owls are not what they seem.";  
my $pattern = '(\s+)';  
my $replacement = '-$1-';  
$text =~ s/$pattern/$replacement/g;  

$text should then be: The- -owls- -are- -not- -what- -they- -seem.

But of course it's more like: The-$1-owls-$1-are-$1-not-$1-what-$1-they-$1-seem.

I tried all kinds of backreferences ($1, \1, \g{1}, \g1) and they all didn't work. The /e modifier didn't work either. Is this possible at all?

The purpose is to alter some text inside an object with a line like this: $object->replace('(.)oo', '$1ar')

Any other ideas how this could be done?

Thank you very much.

Upvotes: 6

Views: 1380

Answers (3)

Dan
Dan

Reputation: 11069

Sinan Ünür's solution will work but it still requires the replacement string to be a literal inside the program at some point. If that replacement string comes from data, you'll have to do something a little fancier:

sub dyn_replace {
  my ($replace) = @_;
  my @groups;
  {
    no strict 'refs';
    $groups[$_] = $$_ for 1 .. $#-;      # the size of @- tells us the number of capturing groups
  }
  $replace =~ s/\$(\d+)/$groups[$1]/g;
  return $replace;
}

and then use it like

$text =~ s/$pattern/dyn_replace($replacement)/eg;

Note that this also avoids eval and allows the use of modifiers like /g. Code taken from this Perl Monks node but I wrote that node so it's ok :)

Upvotes: 3

Sinan Ünür
Sinan Ünür

Reputation: 118128

You could eval and then expand strings using /ee:

my $text = "The owls are not what they seem.";
my $pattern = '(\s+)';
my $replacement = q{"-$1-"};
$text =~ s/$pattern/$replacement/eeg;

From perldoc perlop:

e Evaluate the right side as an expression.

ee Evaluate the right side as a string then eval the result

However, I would feel safer with

my $replacement = sub { "-$1-" };
$text =~ s/$pattern/$replacement->()/eg;

But it all depends on the context in which you are doing this.

Upvotes: 12

Andy Lester
Andy Lester

Reputation: 93676

$text =~ s/$pattern/-$1-/g;

Upvotes: -3

Related Questions