Perl grep函數用法詳解
本文和大家重點學習一下Perl grep函數的用法,Perl grep函數有兩種表達方式,具體是哪兩種請看本文的詳細介紹吧。
Perl grep函數詳解
(一)grep有2種表達方式:
◆grepBLOCKLIST
◆grepEXPR,LIST
BLOCK表示一個code塊,通常用{}表示;EXPR表示一個表達式,通常是正則表達式。原文說EXPR可是任何東西,包括一個或多個變量,操作符,文字,函數,或子函數調用。
LIST是要匹配的列表。
Perl grep函數對列表里的每個元素進行BLOCK或EXPR匹配,它遍歷列表,并臨時設置元素為$_。在列表上下文里,grep返回匹配命中的所有元素,結果也是個列表。在標量上下文里,grep返回匹配命中的元素個數。
(二)grepvs.loops
openFILE"printgrep/terrorism|nuclear/i,;;
這里打開一個文件myfile,然后查找包含terrorism或nuclear的行。;返回一個列表,它包含了文件的完整內容??赡苣阋寻l現,如果文件很大的話,這種方式很耗費內存,因為文件的所有內容都拷貝到內存里了。
代替的方式是使用loop(循環)來完成:
- while($line=;){
- if($line=~/terrorism|nuclear/i){print$line}
- }
上述code顯示,loop可以完成grep能做的任何事情。那為什么還要用grep呢?答案是grep更具Perl風格,而loop是C風格的。
更好的解釋是:(1)grep讓讀者更顯然的知道,你在從列表里選擇某元素;(2)grep比loop簡潔。
一點建議:如果你是Perl新手,那就規矩的使用loop比較好;等你熟悉Perl了,就可使用grep這個有力的工具。
(三)幾個Perl grep函數的示例
1.統計匹配表達式的列表元素個數
$num_apple=grep/^apple$/i,@fruits;
在標量上下文里,grep返回匹配中的元素個數;在列表上下文里,grep返回匹配中的元素的一個列表。
所以,上述code返回apple單詞在@fruits數組中存在的個數。因為$num_apple是個標量,它強迫grep結果位于標量上下文里。
2.從列表里抽取***元素
- @unique=grep{++$count{$_}<2}
- qw(abacddefgfhh);
- print"@uniquen";
上述code運行后會返回:abcdefgh
即qw(abacddefgfhh)這個列表里的***元素被返回了。為什么會這樣呀?讓我們看看:
%count是個hash結構,它的key是遍歷qw()列表時,逐個抽取的列表元素。++$count{$_}表示$_對應的hash值自增。在這個比較上下文里,++$count{$_}與$count{$_}++的意義是不一樣的哦,前者表示在比較之前,就將自身值自增1;后者表示在比較之后,才將自身值自增1。所以,++$count{$_}<2表示將$count{$_}加1,然后與2進行比較。$count{$_}值默認是undef或0。所以當某個元素a***次被當作hash的關鍵字時,它自增后對應的hash值就是1,當它第二次當作hash關鍵字時,對應的hash值就變成2了。變成2后,就不滿足比較條件了,所以a不會第2次出現。
所以上述code就能從列表里***1次的抽取元素了。
◆抽取列表里精確出現2次的元素
- @crops=qw(wheatcornbarleyricecornsoybeanhay
- alfalfaricehaybeetscornhay);
- @duplicates=grep{$count{$_}==2}
- grep{++$count{$_}>;1}@crops;
- print"@duplicatesn";
運行結果是:rice
這里grep了2次哦,順序是從右至左。首先grep{++$count{$_}>;1}@crops;返回一個列表,列表的結果是@crops里出現次數大于1的元素。
然后再對產生的臨時列表進行grep{$count{$_}==2}計算,這里的意思你也該明白了,就是臨時列表里,元素出現次數等于2的被返回。
所以上述code就返回rice了,rice出現次數大于1,并且精確等于2,明白了吧?:-)
3.在當前目錄里列出文本文件
- @files=grep{-fand-T}glob'*.*';
- print"@filesn";
這個就很容易理解哦。glob返回一個列表,它的內容是當前目錄里的任何文件,除了以'.'開頭的。{}是個code塊,它包含了匹配它后面的列表的條件。這只是grep的另一種用法,其實與grepEXPR,LIST這種用法差不多了。-fand-T匹配列表里的元素,首先它必須是個普通文件,接著它必須是個文本文件。據說這樣寫效率高點哦,因為-T開銷更大,所以在判斷-T前,先判斷-f了。
4.選擇數組元素并消除重復
- @array=qw(Tobeornottobethatisthequestion);
- @found_words=
- grep{$_=~/b|o/iand++$counts{$_}<2;}@array;
- print"@found_wordsn";
運行結果是:Tobeornottoquestion
{}里的意思就是,對@array里的每個元素,先匹配它是否包含b或o字符(不分大小寫),然后每個元素出現的次數,必須小于2(也就是1次啦)。
grep返回一個列表,包含了@array里滿足上述2個條件的元素。
5.從二維數組里選擇元素,并且x
- #Anarrayofreferencestoanonymousarrays
- @data_points=([5,12],[20,-3],
- [2,2],[13,20]);
- @y_gt_x=grep{$_->;[0]<$_->;[1]}@data_points;
- foreach$xy(@y_gt_x){print"$xy->;[0],$xy->;[1]n"}
運行結果是:
5,12
13,20
這里,你應該理解匿名數組哦,[]是個匿名數組,它實際上是個數組的引用(類似于C里面的指針)。
@data_points的元素就是匿名數組。例如:
foreach(@data_points){
print$_->;[0];}
這樣訪問到匿名數組里的第1個元素,把0替換成1就是第2個元素了。
所以{$_->;[0]<$_->;[1]}就很明白了哦,它表示每個匿名數組的***個元素的值,小于第二個元素的值。而grep{$_->;[0]<$_->;[1]}@data_points;就會返回滿足上述條件的匿名數組列表。所以,就得到你要的結果啦!
6.簡單數據庫查詢
Perl grep函數的{}復雜程度如何,取決于program可用虛擬內存的數量。如下是個復雜的{}示例,它模擬了一個數據庫查詢:
- #@databaseisarrayofreferencestoanonymoushashes
- @database=(
- {name=>;"WildGinger",
- city=>;"Seattle",
- cuisine=>;"AsianThaiChineseKoreanJapanese",
- expense=>;4,
- music=>;"",
- meals=>;"lunchdinner",
- view=>;"",
- smoking=>;"",
- parking=>;"validated",
- rating=>;4,
- payment=>;"MCVISAAMEX",
- },
- #{...},etc.
- );
- subfindRestaurants{
- my($database,$query)=@_;
- returngrep{
- $query->;{city}?
- lc($query->;{city})eqlc($_->;{city}):1
- and$query->;{cuisine}?
- $_->;{cuisine}=~/$query->;{cuisine}/i:1
- and$query->;{min_expense}?
- $_->;{expense}>;=$query->;{min_expense}:1
- and$query->;{max_expense}?
- $_->;{expense}<=$query->;{max_expense}:1
- and$query->;{music}?$_->;{music}:1
- and$query->;{music_type}?
- $_->;{music}=~/$query->;{music_type}/i:1
- and$query->;{meals}?
- $_->;{meals}=~/$query->;{meals}/i:1
- and$query->;{view}?$_->;{view}:1
- and$query->;{smoking}?$_->;{smoking}:1
- and$query->;{parking}?$_->;{parking}:1
- and$query->;{min_rating}?
- $_->;{rating}>;=$query->;{min_rating}:1
- and$query->;{max_rating}?
- $_->;{rating}<=$query->;{max_rating}:1
- and$query->;{payment}?
- $_->;{payment}=~/$query->;{payment}/i:1
- }@$database;
- }
- %query=(city=>;'Seattle',cuisine=>;'Asian|Thai');
- @restaurants=findRestaurants(@database,%query);
- print"$restaurants[0]->;{name}n";
運行結果是:WildGinger
【編輯推薦】