Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

regex

perl

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.

like image 395
wuwuwu Avatar asked Dec 15 '09 15:12

wuwuwu


2 Answers

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.

like image 187
Sinan Ünür Avatar answered Dec 08 '22 15:12

Sinan Ünür


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 :)

like image 37
Dan Avatar answered Dec 08 '22 14:12

Dan