I have the following code, which replaces a string with a part of it using $1
:
my $string = "abcd1234";
print "$string\n";
$string =~ s/c(d1)2/<found: $1>/;
print "$string\n";
Output:
abcd1234
ab<found: d1>34
Now I want to have variables, which contain the condition and the replacement. But if I do it like this, an error occurs:
my $string = "abcd1234";
print "$string\n";
my $cond = qr/c(d1)2/;
my $rule = "<found: $1>";
$string =~ s/$cond/$rule/;
print "$string\n";
Output:
Use of uninitialized value $1 in concatenation (.) or string
abcd1234
ab<found: >34
I get, that $1
isn't existing in the line, where $rule
is defined. But how can put a placeholder there?
CodePudding user response:
You can use sub_modify
from String::Substitution
:
use String::Substitution qw(sub_modify);
my $string = "abcd1234";
print "$string\n";
my $cond = qr/c(d1)2/;
my $rule = '<found: $1>'; # Single quotes!
sub_modify($string, $cond, $rule);
print "$string\n";
For completeness, note that it's also possible to do this using s///
with the /ee
modifier. However, you shouldn't use it, as it can lead to security issues and various bugs.
CodePudding user response:
You can't delay the interpretation of a variable within a quoted string like that. $1
is substituted as soon as the line is executed.
To do what you seem to want, you would create a sprintf
template and execute it in the replacement part of the substitution with the /e
flag.
my $string = "abcd1234";
print "$string\n";
my $cond = qr/c(d1)2/;
my $replacement_fmt= "<found: %s>";
$string =~ s/$cond/sprintf($replacement_fmt, $1)/e;
print "$string\n";
## ab<found: d1>34