Learning Perl 第三章 列表和數組 Perl的標量表明單數(signal),表明複數(plural)的就是數組和列表。 列表指的是標量的有序集合,數組則是存儲列表的變量。 列表指的是數據,數組指的是變量。 數組或列表中的每一個元素都是單獨的標量變量,擁有獨立的標量值。這些值是有序的,索引從0開始。 數組和列表能夠包含任意多個元素。 經過數組下標,訪問數組中的元素。 數組的長度是沒有上限的,若是須要增補元素,那麼默認取值爲undef。 最後一個元素的索引爲$#rocks。 從數組尾端往回計數的負數數組索引值。 列表直接量 列表直接量(list literal),有圓括號內的逗號隔開的一串數據表示,這些數據就是列表元素。 列表能夠包含任意標量值: ("caoqing", "xiaohuan", "xiaobao") ..範圍操做符。 (1..10) qw 須要創建簡單的單詞列表,能夠省去鍵入引號的麻煩: qw(caoqing, xiaohuan, xiaobao) qw表示"quoted word",Perl都當其爲單引號內的字符串來處理。空白符會被迫棄,剩下的就是列表的元素。 前面的例子是一圓括號做爲定界符(delimiter)。Perl容許用任何標點符號做爲定界符。 qw ! caoqing xiaohuan xiaobao ! qw / caoqing xiaohuan xiaobao / 被圈引的字符串內沒法使用定界符,能夠經過反斜線轉義字符。 列表的賦值 ($caoqing, $xiaohuan, $xiaobao) = ("caoqing", "xiaohuan", "xiaobao"); 當但願引進整個數組,須要在數組名前加上@字符 @rocks = qw / caoqing xiaobao xiaohuan /; @giant = 1..1e5; @stuff = (@rocks, undef, @giant); 數組名會被展開成元素列表,數組只包含標量,不包含其餘數組,因此數組沒法成爲列表裏的元素。 將數組進行復制時,還是列表的賦值運算。 @copy = @quarry; pop和push操做符 要新增元素到數組尾端時,只要將它存放在更高索引對應的新位置。 常把數組當成堆棧(stack)。 pop操做符,負責取出數組中最後一個元素並將其做爲返回值返回。 @array = 1..10; $caoqing = pop(@array); $xiaohuan = pop(@array); print "$caoqing, $xiaohuan"; 10, 9 若是數組爲空,pop返回undef。 push操做符,用於添加一個元素到數組的尾端。 push或者pop的惟一參數都是要操做的數組變量。 @array = 1..10; push(@array, 11); push(@array, 1..10); @other = qw / 3, 5, 6, 2 /; push @array, @others; shift和unshift操做符 對應數組的左邊進行相應的處理。 splice操做符 push-pop,shift-unshift操做符都是針對數組首位端操做的,splice操做符能夠添加或者移除中間的元素。 最多接受四個參數,最後兩個是可選參數。第一個參數是要操做的目標數組,第二個是操做的一組元素的開始位置。 @array = qw (cao qing wang huan xiao bao); @removed = splice(@array, 3); 第三個參數指定要操做的元素長度,第四個參數是要替換的列表。 @array = qw (cao qing wang huan xiao bao); @removed = splice(@array, 1,2,qw(pig)); 字符串中的數組內插 和標量同樣,數組的內容一樣能夠被內插到雙引號串中。內插時,會自動添加分割用空格: @rock = qw {caoqing xiaohuan xiaobao}; print "pig @rock dog\n"; pig caoqing xiaohuan xiaobao dog 數組內插時,首位都不會增長額外的空格; 數組內插時,在處理電子郵件時會有問題,要規避這種問題,須要將@轉義,或者直接用單引號來定義字符串: $email = "caoqing\@gmail.com"; $email = 'caoqing@gmail.com'; 內插數組中的某個元素時,會被替換成該元素的值。 索引表達式會被當成普通字符串表達式處理。 若是要在某個標量變量後面直接寫左方括號,須要先將這個方括號隔開,纔不會被識別爲數組引用的一部分。 @fred = qw (caoqing love xiao bao); $fred = "xiaohuan"; print "This is $fred[3]\n"; print "This is ${fred}[3]\n"; print "This is $fred"."[3]\n"; print "This is $fred\[3\]\n"; This is bao This is xiaohuan[3] This is xiaohuan[3] This is xiaohuan[3] foreach控制結構 若是對整個列表和數組進行處理很是方便,Perl提供另外一種控制結構。 foreach(循環)中能逐項遍歷列表中的值,一次迭代: foreach $i (qw {caoqing xiaohuan xiaobao}){ print "One name is $i.\n"; } One name is caoqing. One name is xiaohuan. One name is xiaobao. 存儲的變量在foreach循環變量循環結束後還原,沒必要擔憂前面是否用過同名的變量。 Perl內置變量:$_ foreach循環開頭省略控制變量,Perl使用默認變量:$_。 foreach (qw {caoqing xiaohuan xiao bao}){ print "One name is $_.\n"; } One name is caoqing. One name is xiaohuan. One name is xiao. One name is bao. reverse操做符 reverse操做符會讀取列表的值,並按照相反的順序返回該列表。 @cao = (1..10); @qing = reverse(@cao); Perl會先計算等號右邊要賦的值,在實際進行操做。 reverse會返回次序相反的列表,並不會修改傳進來的參數。 sort操做符 sort操做符會讀取列表的值,而根據內部字符編碼順序進行排序。大的字符排列在前面,數組在字母前,標點散落各處。 sort操做符的參數應該是某個輸入列表,而後進行排序,繼而返回排序後的列表。 @rock = qw (caoqing xiaohuan xiao bao); @sorted = sort(@rock); foreach (@sorted) { print "$_\t"; } bao caoqing xiao xiaohuan each操做符 Perl5.12開始,能夠針對數組使用each操做。以前只能用於提取哈希的鍵值對。 對數組調用each,會返回該元素的索引和該元素的值: @rock = qw (caoqing xiaohuan xiao bao); while(my ($index, $value) = each(@rock)) { print "$index : $value\n"; } 0 : caoqing 1 : xiaohuan 2 : xiao 3 : bao 若是不是用each實現,能夠根據索引進行遍歷,而後藉助索引值取得元素值: my @rock = qw (caoqing xiaohuan xiao bao); foreach $index (0..$#rock) { print "$index : $rock[$index]"; } 0 : caoqing1 : xiaohuan2 : xiao3 : bao 標量上下文和列表上下文 同一個表達式出如今不一樣的位置會有不一樣的意義。 所謂上下文,指的是如何使用表達式。 Perl解析表達式時,要麼返回標量,要麼返回列表。 42 + some sort some some這個單詞在某種狀況下獲得單一的標量值,而在另外狀況下獲得一個列表。Perl老是根據須要的上下文返回對應的值。 數組名稱爲例,在列表上下文,返回元素的列表;在標量上下文,返回數組中元素的個數: @animal = qw (dog cat pig); @sorted = sort @animal; $number = 42 + @animal; print "$number"; 45 在標量上下文中使用產生列表的表達式 某些表達式不會在標量上下文中返回任何值。 一些常見的上下文: $fred = something; #標量上下文 @animal = something; #列表上下文 ($cao, $qing) = something; #列表上下文 ($bao) = something; #列表上下文 若是給列表或者數組賦值,就是列表上下文。 標量上下文: $fred = something; $fred[3] = something; 123 + something; if (something) {...}; while (something) {...}; $fred[somthing] = something; 列表上下文: @fred = something; ($fred, $cao) = something; ($cao) = something; push @fred, something; foreach $fred (something) {...}; sort something; reverse something; print something; 在列表上下文使用產生標量的表達式 @fred = 6 * 7; @qing = "hello" . '' . "world"; 強制指定標量上下文 Perl要在列表上下文的地方強制使用標量上下文,可使用僞函數scalar。 @rocks = qw / cao qing wang huan /; print "How many rocks do you have?\n"; print "I have ", scalar rocks, "rocks.\n"; 習題 1. 寫一個程序,讀入一些字符串,直到文件結尾爲止。而後,按照相反順序輸出這個列表。 2. 寫一個程序,讀入一些數字,而後根據數字輸出以下名單中相應的人名。 cao qing wang huan xiao bao 3. 寫一個程序,讀入一些字符串,而後按照ASCII碼順序輸出全部字符串。 答案: 1. print "Please enter some lines, then press Ctrl-D:\n"; print reverse <STDIN>; 2. @name = qw( cao qing wang huan xiao bao ); print "Enter some numbers from 1 to 6, one per line, then press Ctrl-D:\n"; chomp(@numbers = <STDIN>); foreach (@numbers) { print "$name[$_ - 1]\n"; } 3. chomp(@lines = <STDIN>); @sorted = sort @lines; print "sortedz\n";