2010-12-18 49 views
2

我想教自己的Perl和我到處尋找答案可能是一個非常簡單的問題。我定義了一個子程序,我打電話來計算單詞中的字母數量。如果我這樣寫出來:初學者調用一個Perl子程序

$sentence="This is a short sentence."; 

@words = split(/\s+/, $sentence); 

foreach $element (@words) { 
    $lngths .= length($element) . "\n"; 
} 
print "$lngths\n"; 

然後它就像一個魅力。但是,如果我將它包裝到一個子例程中,分割不會分割輸入,而是將整個句子統計爲單個輸入。下面是我如何定義子程序:

sub countWords { 
    @words = split(/\s+/, @_); 
    foreach $element(@words) { 
     $lngths .= length($element) . "\n"; 
    } 
    return $lngths; 
} 

從我請教這應該工作我讀過的所有網頁和文本,但事實並非如此。

在此先感謝!

+5

你可以馬上做到,以進一步您的Perl學習的最好的事情就是*總*包括'使用嚴格;使用警告;'在每個文件的頂部。 – Ether 2010-12-19 04:04:47

回答

13

問題是您使用@_。這是一個數組,但你像標量一樣訪問它。

@_包含此功能的所有參數。它的樣子,你傳遞了一句話,你想分裂它。這裏有一些可能的方式來做到這一點:

@words = split(/\s+/, $_[0]); 

這意味着「採取第一個參數的功能和拆分」。

或者:

my $sentence = shift; 
@words = split(/\s+/, $sentence); 

這是幾乎相同的,但使用一箇中間變量的可讀性。


其實,你在做什麼是:

@words = split(/\s+/, @_); 

這意味着:

  • 解釋@_作爲一個標量,這意味着在@_元素( 1,在這種情況下)
  • 分割字符串"1" whitespa CE

它返回數組:

@words = ("1"); 
+0

D'oh!這是有道理的,我真的很感謝澄清。 – 2010-12-18 20:37:39

3

你得從內森回答的主要部分;剩下的觀察是大多數人不會將標點符號和數字計爲字母,但是您的子程序會這樣做。我可能會去:

sub countLetters 
{ 
    my($sentence) = @_; 
    $sentence =~ s/[^[:alpha:]]//gm; 
    return length($sentence); 
} 

這裏的關鍵點是圍繞my子句中的變量列表中的括號內。在一般情況下,你有幾個參數傳遞到子,並且你可以將他們的(副本)變量在子程序這樣的:

my($var1, $var2, $var3) = @_; 

括號提供名單上下文「,並確保的第一個元素@_被複制到$var1,第二個到$var2等等。沒有括號,你有'標量上下文',並且當在標量上下文中計算數組時,返回的值是數組中元素的數量。因此:

my $var1, $var2, $var3 = @_; 

將可能分配3 $var1(因爲三個值被傳入到該子程序)和$var1$var2都希望能undef

正則表達式從字符串中刪除所有非字母字符;字母的數量是剩下的長度。

0

在計算字符時,perl的音譯操作符經常派上用場。 計數非空白字符,而無需分割你的字符串轉換成單獨的單詞,你可以這樣做:

$lngths = $sentence =~ tr/ \t\f\r\n//c;