Re: Using qr// with substitution and group-interpolation in the substitution part

[email protected] (Levi Elias Nystad-Johansen via beginners) Wed, 25 Oct 2023 19:00:20 +0000
Newsgroups perl.beginners
Message-ID <FxuwC8tmhPIw_uFIS0Jj456iJxCpPmXEEZw1ANhT2O-rjv2xZ7juAnvjBaG6DytbJIAsbOLQ2wV7pBFBmztnVfs7jyl531uozw3XgspMv7I=@protonmail.com>
That looks like a solid solution to me 👍
We can avoid using $_[0] by topicalizing with a for-loop:

sub substitute_lines {
my ($contents, $subst) = @_;
$subst->() for ($contents);
return $contents;
}

my $data = "foo whatever bar";

print substitute_lines($data, sub { s/^foo (whatever) bar$/bar $1 baz/mg });

If one really wants to pass the substitute as a separate argument, we could use eval:

sub substitute_lines {
my ($contents, $regex, $subst) = @_;
while($contents =~ /$regex/m)
{
my $replacement = eval qq("$subst");
$contents =~ s/$&/$replacement/mg;
}
return $contents;
}

my $data = "foo whatever bar";

print substitute_lines($data, qr/^foo (whatever) bar$/, 'bar $1 baz');

But this is ugly, and slow.

-L

------- Original Message -------
On Wednesday, October 25th, 2023 at 8:01 PM, Andrew Solomon <[email protected]> wrote:

> That's a fun question, Josef!
>
> I don't think you can pass a replacement phrase around, so this is all I came up with:
>
> sub substitute_lines {
> my ($contents, $subst) = @_;
> $contents = $subst->($contents);
> return $contents;
> }
>
> my $data = "foo whatever bar";
> print(substitute_lines($data, sub { $_[0] =~ s/^foo (whatever) bar$/bar $1 baz/mgr } ));
>
> I'd be very pleased if someone could come up with a more elegant solution.
>
> On Wed, Oct 25, 2023 at 6:34 PM Josef Wolf <[email protected]> wrote:
>
>> Hallo all,
>>
>> maybe this is not exactly a beginner question, but I could not find an
>> appropriate mailing list (all other lists seem to be developer realted).
>>
>> Basically, I want to do the same as
>>
>> $data =~ s/^foo (whatever) bar$/bar $1 baz/mg;
>>
>> but with a different interface (because it has to be embedded into a bigger
>> project), So I have come with this;
>>
>> sub substitute_lines {
>> my ($contents, $regex, $subst) = @_;
>> $contents =~ s/$regex/$subst/mg;
>> return $contents;
>> }
>> }
>>
>> &substitute_lines ($data, qr/^foo (whatever) bar$/mg, 'bar $1 baz');
>>
>> Which (mostly) works as expected. Unfortunately, this won't interpolate the
>> matched group $1.
>>
>> Experiments which also do not work:
>>
>> &substitute_lines ($data, qr/^foo (whatever) bar$/mg, "bar $1 baz");
>> # obviously, $1 is interpolated _before_ re-match is done
>>
>> &substitute_lines ($data, qr/^foo (whatever) bar$/mge, '"bar $1 baz"');
>> # /e modifier not accepted
>>
>> Any hints?
>>
>> --
>> Josef Wolf
>> [email protected]
>>
>> --
>> To unsubscribe, e-mail: [email protected]
>> For additional commands, e-mail: [email protected]
>> http://learn.perl.org/