Why won't my Perl function work?

I'm having problems with the 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 that will not work. I thought the arguments were sent by reference in Perl. String my($regex, $replacement, $text) = @_; then copy them? How to fix it?

+4
source share
4 answers

You are changing the copy of $text that you passed; It will not affect 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 above code works because the @_ elements are similar to the variables passed to. But Adnan's answer is most often fulfilled. Changing the arguments passed to functions is an amazing behavior and does things like template_replace(qr/foo/, "bar", "foo is foo") , doesn't work.

+8
source
 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 (..) = @_ copies the arguments. Therefore, if you modify a variable, you need to return it if it is not global.

+10
source

This is part of the β€œassignment” of a routine that creates copies of data.

If you modify the @_ arguments directly, they work as you expect. This, however, is 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.] 
+4
source

Here is an option on how to do this, 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, not implied. In practice, it works identically to Chas. Owens , but uses scalar refs instead of relying on an understanding of array behavior.

This will become more apparent to anyone reading your code that the TemplateReplace function intentionally modifies $ text.

In addition, he will tell you that you are using it incorrectly, cursing:

  Can't use string ("This is a test.") As a SCALAR ref while "strict refs" in use at replace.pl line 9.

If you accidentally forgot \ somewhere.

0
source

All Articles