Reputation: 67759
I am having trouble with a function I wrote...
sub TemplateReplace
{
my($regex, $replacement, $text) = @_;
$text =~ s/($regex)/($replacement)/gs;
}
my $text = "This is a test.";
TemplateReplace("test", "banana", $text);
But it doesn't work. I thought arguments were sent by reference in Perl. Does the line my($regex, $replacement, $text) = @_;
then copy them? How do I fix this?
Upvotes: 4
Views: 387
Reputation: 11079
It's the "assignment" part of the sub-routine that is making the copies of the data.
If you modify the @_ arguments directly, they work as you expect. It is however, not very readable. :-)
use strict;
umask(0);
$|=1;
my $debug = 0;
my $text = "This is a test.";
print "Before 1: [$text]\n";
TemplateReplace("test", "banana", $text);
print "After 1: [$text]\n";
print "Before 2: [$text]\n";
TemplateReplace2("test", "banana", $text);
print "After 2: [$text]\n";
sub TemplateReplace
{
my ($regex, $replacement, $text) = @_;
$text =~ s/($regex)/($replacement)/gs;
}
sub TemplateReplace2
{
$_[2] =~ s/$_[0]/$_[1]/gs;
}
returns:
Before 1: [This is a test.]
After 1: [This is a test.]
Before 2: [This is a test.]
After 2: [This is a banana.]
Upvotes: 4
Reputation: 57354
Here is a variation on how to do it, which is almost identical to your code with a slight difference.
use strict;
use warnings;
sub TemplateReplace {
my($regex, $replacement, $text) = @_;
$$text =~ s/($regex)/$replacement/gs;
}
my $text = "This is a test.";
TemplateReplace("test", "banana", \$text);
print $text;
This behavior is explicit instead of implicit. In practice, it works identically to Chas. Owens result, but uses scalar-refs instead of relying on understanding the behaviour of arrays.
This will make it more obvious to anybody reading your code that the function "TemplateReplace" is intentionally modifying $text.
Additionally, it will tell you you're using it wrong by squawking with :
Can't use string ("This is a test.") as a SCALAR ref while "strict refs" in use at replace.pl line 9.
If you happen to forget the \ somewhere.
Upvotes: 0
Reputation: 64919
You are modifying a copy of the $text
you passed in; this will have no effect on the original.
#!/usr/bin/perl
use strict;
use warnings;
my $text = "This is a test.";
template_replace(qr/test/, "bannana", $text);
print "$text\n";
sub template_replace {
my $regex = shift;
my $replacement = shift;
$_[0] =~ s/$regex/$replacement/gs;
}
The code above works because the elements of @_ are aliased to the variables passed in. But Adnan's answer is the more commonly done. Modifying arguments passed into functions is surprising behavior and makes things like template_replace(qr/foo/, "bar", "foo is foo")
not work.
Upvotes: 8
Reputation: 2967
sub TemplateReplace
{
my($regex, $replacement, $text) = @_;
$text =~ s/($regex)/($replacement)/gs;
return $text;
}
my $text = "This is a test.";
$text = TemplateReplace("test", "banana", $text);
There. That should work.
And yes, your my( ..) = @_ does copy the args. So if you're modifying a variable, you need to return it unless it's a global.
Upvotes: 10