Hello,

I tried to find a solution that doesn't use eval, although if '$1' is sent as a parameter to the subroutine as a simple string, I think it either need to be eval'ed or replaced literally.
I made this solution to work with more capturing parans if necessary:

use strict;
use warnings;

my $data = "foo whatever bar";
$data = substitute_lines( $data, qr/^foo (whatever) bar$/, 'bar $1 baz');
print "$data\n";

$data = "foo whatever bar whatever2 baz";
$data = substitute_lines( $data, qr/^foo (whatever) bar (whatever2) baz$/, 'bar $2 baz $1 foo');
print "$data\n";

sub substitute_lines {
   my ($contents, $regex, $subst) = @_;
$contents =~ s/$regex(?{ $contents =~ s[$regex][$subst]gm; my @c = @{^CAPTURE}; $contents =~ s[\$$_][$c[$_-1]] for 1 .. @c })/$contents/;
   return $contents;
}

It prints:
bar whatever baz
bar whatever2 baz whatever foo

However, the regex above uses code interpretation in regex, which is another kind of eval. So the following subroutine does the same thing with a simple replacement, without code interpretation:

sub substitute_lines {
   my ($contents, $regex, $subst) = @_;
   $contents =~ s/$regex/$subst/gm;
   my @matches = @{^CAPTURE};
   $contents =~ s/\$$_/$matches[$_-1]/g for 1 .. @matches;
   return $contents;
}

----- Original Message ----- From: "Claude Brown via beginners" <beginners@perl.org> To: "Levi Elias Nystad-Johansen" <levi.johan...@protonmail.com>; "Andrew Solomon" <and...@geekuni.com>
Cc: "Josef Wolf" <j...@raven.inka.de>; <beginners@perl.org>
Sent: Thursday, October 26, 2023 12:07 AM
Subject: RE: Using qr// with substitution and group-interpolation in the substitution part


Josef,

Inspired by Levi's “eval” idea, here is my solution:

sub substitute_lines {
   my ($contents, $regex, $subst) = @_;
   eval "\$contents =~ s/$regex/$subst/g";
   return $contents;
}

$data = "foo whatever bar";
$data = &substitute_lines($data, qr/^foo (whatever) bar$/m, 'bar $1 baz');
print "$data\n";

The differences:
- escaped the "$" so the eval gets a literal "$contents"
- didn't escape "$" so the eval receives the value of $regex and $subst
- moved the "g" into the sub as it has no meaning for a qr//
- removed the "m" from the sub as it best left with the original qr//
- added "$data = ..." to get back the value from the subroutine

Cheers,

Claude.




--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to