2011-08-02 59 views
2

假設我必須使用單個取代做這個替代,什麼是避免這種錯誤的優選方法:未初始化向引用在換人

Use of uninitialized value $2 in concatenation (.) or string at -e line 1.

有了這個Perl代碼:

perl -e 'use strict;use warnings;my $str="a";$str=~s/(a)|(b)/$1foo$2/gsmo;'

目標這裏是根據$str包含什麼打印「afoo」或「foob」。

我可以使用no warnings;但後來我擔心我會錯過其他「真實」的警告。我也知道使用一種模式會讓這個錯綜複雜,但我的實際模式要複雜得多。

如果你關心的實際替代品更接近:

#!perl 
my $search = q~(document\.domain.*?</script>)|(</head>)~; 
my $search_re = qr/$search/smo; 
my $replace = q("$1 
<script src=\"/library.js\"></script> 
$2"); 
while (<*.tmpl>) { 
    my $str = fead_file($_); 
    $str =~ s/$search_re/$replace/gee; 
}

但更復雜,基本上上面的代碼只是從數據庫中讀取,以獲得搜索和替換,然後將它們確實給模板。每次提交都要運行這個腳本兩次會引入太多的開銷,顯然...所以他們說...

+1

爲什麼不在循環中做兩個不同的搜索和替換操作?與只需讀取文件的時間相比,應該無法檢測到開銷。 – Nemo

+0

循環是我無法更改的庫。我只能提供替代。 – Rob

回答

2

您可以:

my $replace = q("@{[$1||'']} 
<script src=\"/library.js\"></script> 
@{[$2||'']}"); 

(使用//代替||上5.10+)

+0

偉大的,這解決了這個問題 – Rob

0

那麼,當你具體說OR()時,你找不到「a」和「b」 |)。此外,您不能通過將變量名稱放在文本旁邊來連接字符串,例如$1foo

我不太清楚你對開銷的看法,但你需要檢查匹配以便做出正確的替換。

s/(a)/$1 . "foo"/ge || s/(b)/"foo" . $1/ge; 

這可能有效。如果第一個工作,第二個不會執行(短路OR)。

+0

看看「更接近」真實的例子;替代是a/g,所以推測這兩種替代都可能發生,而短路將不起作用。 – ysth

+0

@ysth啊,我明白你的意思了。然而,「$ 1」和「$ 2」真的可以在OR情況下工作嗎?目前我無法訪問perl。 – TLP

+0

他們工作的意義,其中一個或另一個將是undef – ysth

1

仍然有效,與/ G:

s/(a)|(b)/ ($1 // '') . 'foo' . ($2 // '') /ge 
0

類似池上的解決方案,如果你想要在變量中保存替換,您可以調用s///e中的代碼引用,將它傳遞給捕獲。

#!perl 
my $search = q~(document\.domain.*?</script>)|(</head>)~; 
my $search_re = qr/$search/smo; 
my $replace = sub { 
    my $one = shift || ''; 
    my $two = shift || ''; 
    return qq($one\n<script src="/library.js"></script>\n$two); 
} 
while (<*.tmpl>) { 
    my $str = fead_file($_); 
    $str =~ s/$search_re/$replace->($1, $2)/ge; 
}