2009-04-11 60 views
4

我有我寫了一個函數的麻煩......爲什麼我的Perl函數不能工作?

sub TemplateReplace 
{ 
    my($regex, $replacement, $text) = @_; 
    $text =~ s/($regex)/($replacement)/gs; 
} 

my $text = "This is a test."; 
TemplateReplace("test", "banana", $text); 

但它不工作。我認爲參數是通過Perl中的引用發送的。那麼行my($regex, $replacement, $text) = @_;然後複製它們?我該如何解決?

+1

在我們弄清楚如何解決它之前,你必須解釋你想要發生什麼。你想改變原始變量,還是獲取一個顯示修改的新字符串?這是Chas之間的區別。和阿德南的回答。 :) – 2009-04-11 17:53:38

+0

如果您試圖編輯魔法般的參數,Chas的答案就是您正在尋找的答案。如果你願意這樣做的話,請按照Adnan的說法。遠處變化的變量通常會被忽略,它通常只會增加複雜性,而沒有多少好處。 – Danny 2009-04-11 18:48:04

回答

8

要修改的$text你傳遞的複印件;這對原文沒有影響。

#!/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; 
} 

上面的代碼工作,因爲@_的元素的別名是要在傳遞的變量,但Adnan的答案是較爲常見的做。修改傳遞給函數的參數是令人驚訝的行爲,並且使得像template_replace(qr/foo/, "bar", "foo is foo")這樣的東西無法工作。

10
sub TemplateReplace 
{ 
    my($regex, $replacement, $text) = @_; 
    $text =~ s/($regex)/($replacement)/gs; 
    return $text; 
} 

my $text = "This is a test."; 
$text = TemplateReplace("test", "banana", $text); 

那裏。這應該工作。

是的,你的我的(..)= @_確實複製了參數。所以如果你修改一個變量,除非它是全局的,否則你需要返回它。

+0

對於正確的方法+1,儘管查斯。歐文斯的回答幫助我瞭解了更多。 – rlbond 2009-04-11 19:15:15

4

這是製作數據副本的子例程的「賦值」部分。

如果您直接修改@_參數,它們將按照您的預期工作。但是,它不是很可讀。 :-)

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; 
    } 

回報:

Before 1: [This is a test.] 
After 1: [This is a test.] 
Before 2: [This is a test.] 
After 2: [This is a banana.] 
0

下面是如何做到這一點的變體,它與您的代碼幾乎完全相同,但略有不同。

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; 

此行爲是明確而不是隱含。實際上,它的作用與Chas. Owens結果相同,但使用標量引用而不是依賴於理解數組的行爲。

這會讓閱讀代碼的人更加明白,「TemplateReplace」的功能是故意修改$ text。

此外,它會告訴你正在使用它錯用唧唧喳喳:

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

如果你碰巧地方忘了\。

相關問題