學習perl(2)

湖湘文化發表於2013-11-19
 

學習Perl2
列表和陣列
1)特殊的陣列索引值
假如對索引值超過陣列尾端的元素賦值,陣列將會依需要自動擴大---只要有可用的記憶體配置給Perl,陣列的長度是沒有上限的。必要時,插入的元素會自動產生,並設成undef值。把$#name當成索引值的做法十分常見,還可以 從陣列尾端往回計數“負數陣列索引值”
2)列表直接量
(1,2,3,) (1,2,3) (1..100) ($a,17) (“fred”, “betty”) 幾個示例
qw(quoted word)縮寫
Perl程式裡,經常要建立簡單的單詞列表,這時可以使用qw簡寫,省去鍵入一堆額外引號的時間:qw/ fred betty / 界定符還可以是其他的,如!{<[
qw列表中,不能像雙引號內的字串一樣使用n$fred;因為qw是一種引號,所以不能將註釋放在qw列表中。
3)列表的賦值
因為列表是在賦值運算開始之前建立的,所以在Perl裡互換兩個變數的值相當容易:
($fred,$betty) = ($betty,$fred); #互換兩者的值
引用整個陣列時,只要在陣列之前加上一個@符號(而且後面沒有出現索引的方括號)就可以了,如:@rocks = qw/ bedrock slate / ;
pop
push運算子:把陣列當成堆疊來用是很常見的做法,這時,專案的新增和移除都是在右手邊進行的(就是陣列裡位於“最後面”的那一端)。
pop運算子可用來取出陣列中最後一個元素並且將它返回:
@array = 5..9; $fred = pop(@array); #$fred變成9@array現在變成(5,6,7,8)
如果陣列是空的,那麼pop不會變動它,而且會返回undef
push運算子和pop相反,它會新增一個元素或者一串元素到陣列的尾端:push(@array,0);
注意:push的第一個引數或pop的唯一引數必須是陣列變數,對列表直接量進行pushpop操作是毫無意義的。
shiftunshift運算子:對陣列的“開頭“進行相應的操作:
pop類似,對於一個空的陣列變數,shift會返回undef

4)foreach控制結構
foreach迴圈會逐項處理列表的值,每次對一個值執行迴圈裡的操作:
#!/usr/bin/perl -w

foreach $rock (qw/ bedrock slate lava /) {

print "One rock is $rock.n";

}
改進後Perl所支援的做法:
#!/usr/bin/perl -w

@rocks = qw/ bedrock slate lava /;

foreach $rock (@rocks) {

$rock = "t$rock";

$rock .= "n";

}

print "The rocks are:n", @rocks;

Perl
最愛的預設變數$_
假如你在foreach迴圈的開頭省略了控制變數,Perl會使用它最愛的預設變數$_
#!/usr/bin/perl -w

foreach (1..10) {

print "I can not count to $_!n";

}
#!/usr/bin/perl -w

$_ = "Yabba dabba doon";

print;

reverse
運算子:reverse會讀取列表的值(可能來自陣列)並依相反的次序返回該列表
#!/usr/bin/perl -w

@fred = 6..10;

@fred = reverse @fred;

print "The freds now are: @fred.n";
注意:reverse運算子會返回次序相反的列表,但它並不會影響自己的引數,所以假如返回值沒有被賦值到任何地方,它將毫無意義:
reverse @fred ; #錯:不會改變@fred @fred = reverse(@fred); #好多了

類似reverse的運算子sort,排序的順序就是ASCII編碼的順序
對陣列排序時,必須將排序的結果存回陣列:@rocks = sort @rocks;
#!/usr/bin/perl -w

@fred = 97..102;

@fred = sort @fred;

print "The freds now are: @fred.n";

5)標量上下文與列表上下文
“上下文”指的就是表示式所出現的位置。解析表示式時,Perl會希望它是“標量值”或“列表值”的其中之一,此處,Perl所希望的,就稱為表示式的上下文。
Perl中,表示式的返回值一定會符合它們的上下文。以陣列的“名稱”為例:在列表上下文中,它會產生元素的列表;在標量上下文中,它會返回陣列中元素的個數:

@people = qw( fred barney betty );
@sorted = sort @people; #
列表上下文: barney betty fred)
@number = 42 + @people; #
標量上下文:42 + 3等於45
@list = @people; #
包含3個人名的列表

$n = @people; #數字3
#!/usr/bin/perl -w

@people = qw( fred barney betty );

@sorted = sort @people;

@number = 42 + @people;

@list = @people;

$n = @people;

print "The number of people are : $n.n";

print "The list ; @list.n";

print "The number : @number.n";

printf "The sorted : @sorted.n";
注意:但請不要立刻得出結論,在標量上下文中一定會得到列表上下文中所返回元素的個數。

在標量上下文中使用產生列表的表示式
除非有人提出別的實現方式,否則sort在標量上下文中總是會返回undef
在列表上下文中,reserve會返回反序過的列表;在標量上下文中,它則會返回反序過的字串:
#!/usr/bin/perl -w

@backwards = reverse qw/ yabba dabba doo /;

print "The list of backwards are: @backwards.n";

$backwards = reverse qw/ yabba dabba doo /;

print "The scalar of backwards are: $backwards.n";
不要被只有一個元素的列表給騙了,($dino) = something;這個還是列表上下文。只要元素是賦值給列表的(不管元素的個數),它就是列表上下文。假如你將元素賦值給陣列,它也還是列表上下文。

在列表上下文中使用產生標量的表示式
這裡的轉換十分直接:假如表示式的求值結果不是列表值(也就是標量值),則標量值會被自動提升為含有單一元素的列表:@fred = 6 * 7; #變成含有單一元素的列表{42}
空列表的正確賦值法: @betty = (); 而不是:@betty = undef;
因為undef是標量值,所以將undef賦值給陣列無法清空該陣列。直接使用空列表賦值可能是比較好的辦法。
@fred = 6 * 7;

print "The result of fred is : @fred.n";

@barney = " Hello" . ' ' . "world";

print "The result of barney is :@barney.n";

@betty = ();

print "The result of betty is : @bettyn";

強制指定標量上下文
有時候,需要在Perl期望列表上下文的時候,強制指定標量上下文,此時可以使用假函式scalar,它不是真的函式,只是用來告訴Perl必須提供標量上下文:
#!/usr/bin/perl -w

@rocks = qw( talc quartz jade obsidian );

print "How many rocks do you have?n";

print "I have ",scalar @rocks," rocks!n";
print "I have ", @rocks," rocks!n"; #
錯,這會輸出各種石頭的名稱

列表上下文中的

在標量上下文中會返回輸入資料的下一行;在列表上下文中,則會返回剩餘的各行,直到檔案結尾為止,所返回的每一行都將成為列表中單獨的元素。
輸入資料的來源是鍵盤時,產生檔案結尾符號的方式:UNIX及其類似的系統,鍵入Ctrl + D、對於DOSWindows之類,鍵入Ctrl + Z
@lines = ; #讀取所有資料行 chomp(@lines); #忽略所有換行符
或者更簡潔的 chomp(@lines = ); #讀取所有資料行,但不包括換行符



習題:
1)讀入一串字串(每行一個),直到檔案結尾為止,然後以相反順序輸出這個列表。(如果輸入來自鍵盤,鍵入Ctrl + DCtrl + Z來結束輸入)
#!/usr/bin/perl -w

print "Please enter a tring,each line for one:n";

print "When you finished it,please enter Ctrl + Dn";

chomp(@lines = );

@lines = reverse @lines;

print "The result is ; @lines.n";
參考答案如下:
#!/usr/bin/perl -w

print "Enter some lines,then press Ctrl-D:n";

@lines = ;

@reverse_lines = reverse @lines;

print @reverse_lines;
#!/usr/bin/perl -w

print "Enter some lines,then press Ctrl-D:n";

print reverse;
2
)讀入一串字串(每行一個),直到檔案結尾為止,然後根據每一個數字,輸出如下名單(fred betty dino wilma pebbles bamm-bamm)中相應的人名。
#!/usr/bin/perl -w

print "Please enter some numbers,each line for one,then enter Ctrl + D:n";

@names = qw / fred betty dino wilma pebbles bamm-bamm /;

chomp(@values = );

foreach (@values) {

print "$names[$_ -1 ]n";

}
參考答案如下:
#!/usr/bin/perl -w

print "Please enter some numbers,each line for one,then enter Ctrl + D:n";

@names = qw / fred betty dino wilma pebbles bamm-bamm /;

chomp(@values = );

foreach (@values) {

print "$names[$_ -1 ]n";

}
3

#!/usr/bin/perl -w

print "Pleas enter lines,each line for one string,then enter Ctrl + D:.n";

print sort();
參考答案如下:
#!/usr/bin/perl -w

chomp(@lines = );

@sorted = sort @lines;

print "@sortedn";
讓每一行分開顯示的做法: print sort ;


子例程
1)定義子例程
定義你自己的子例程時,將會用到關鍵字sub、子例程的名稱(不含&符號)以及(花括號內)經縮排的構成子例程主體的程式程式碼塊:(子例程的定義可以放在程式中的任何地方)
#!/usr/bin/perl -w

sub marine {

$n += 1;

print "Hello,sailor number $n!n";

}

2
)呼叫子例程
任何表示式中只要使用了子例程的名稱(加上&符號),就會呼叫子例程:&marine;
3
)返回值
Perl中,任何子例程都有返回值,子例程並沒有分成有返回值和沒有返回值兩種。
#!/usr/bin/perl -w

sub sum_of_fred_and_barney {

print "Hey,you called the sum_of_fred_and_barney subroutine!n";

$fred + $barney;

}

$fred = 3;

$barney = 4;

$c = &sum_of_fred_and_barney;

print "$c is $c.n";

$d = 3 * &sum_of_fred_and_barney;

print "$d is $d.n";

sub larger_of_fred_and_barney {

if ($fred > $barney){

$fred;

} else {

$barney;

}

}

$fred = 3;

$barney = 4;

$c = &larger_of_fred_and_barney;

print "The larger is $c.n";

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21256317/viewspace-776980/,如需轉載,請註明出處,否則將追究法律責任。