perl中grep用法總結 z

來源:互聯網
上載者:User

一) Grep函數grep有2種表達方式:grep BLOCK LISTgrep EXPR, LISTBLOCK表示一個code塊,通常用{}表示;EXPR表示一個運算式,通常是Regex。原文說EXPR可是任何東西,包括一個或多個變數,操作符,文字,函數,或子函數調用。LIST是要匹配的列表。grep對列表裡的每個元素進行BLOCK或EXPR匹配,它遍曆列表,並臨時設定元素為$_。在列表上下文裡,grep返回匹配命中的所有元素,結果也是個列表。在標量上下文裡,grep返回匹配命中的元素個數。(二) Grep vs. loopsopen FILE "<myfile" or die "Can't open myfile:$!";print grep /terrorism|nuclear/i,<FILE>;;這裡開啟一個檔案myfile,然後尋找包含terrorism或nuclear的行。<FILE>;返回一個列表,它包含了檔案的完整內容。可能你已發現,如果檔案很大的話,這種方式很耗費記憶體,因為檔案的所有內容都拷貝到記憶體裡了。代替的方式是使用loop(迴圈)來完成:while ($line = <FILE>;) {if ($line =~ /terrorism|nuclear/i) { print $line }}上述code顯示,loop可以完成grep能做的任何事情。那為什麼還要用grep呢?答案是grep更具perl風格,而loop是C風格的。更好的解釋是:(1)grep讓讀者更顯然的知道,你在從列表裡選擇某元素;(2)grep比loop簡潔。一點建議:如果你是perl新手,那就規矩的使用loop比較好;等你熟悉perl了,就可使用grep這個有力的工具。(三) 幾個grep的樣本1. 統計匹配運算式的列表元素個數$num_apple = grep /^apple$/i, @fruits;在標量上下文裡,grep返回匹配中的元素個數;在列表上下文裡,grep返回匹配中的元素的一個列表。所以,上述code返回apple單詞在@fruits數組中存在的個數。因為$num_apple是個標量,它強迫grep結果位於標量上下文裡。2. 從列表裡抽取唯一元素@unique = grep { ++$count{$_} < 2 }         qw(a b a c d d e f g f h h);print "@unique\n";上述code運行後會返回:a b c d e f g h即qw(a b a c d d e f g f h h)這個列表裡的唯一元素被返回了。為什麼會這樣呀?讓我們看看:%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. 抽取列表裡精確出現2次的元素@crops = qw(wheat corn barley rice corn soybean hay       alfalfa rice hay beets corn hay);@duplicates = grep { $count{$_} == 2 }       grep { ++$count{$_} >; 1 } @crops;print "@duplicates\n";運行結果是:rice這裡grep了2次哦,順序是從右至左。首先grep { ++$count{$_} >; 1 }@crops;返回一個列表,列表的結果是@crops裡出現次數大於1的元素。然後再對產生的臨時列表進行grep { $count{$_} == 2}計算,這裡的意思你也該明白了,就是臨時列表裡,元素出現次數等於2的被返回。所以上述code就返回rice了,rice出現次數大於1,並且精確等於2,明白了吧? 3. 在目前的目錄裡列出文字檔@files = grep { -f and -T } glob '* .*';print "@files\n";這個就很容易理解哦。glob返回一個列表,它的內容是目前的目錄裡的任何檔案,除了以'.'開頭的。{}是個code塊,它包含了匹配它後面的列表的條件。這隻是grep的另一種用法,其實與 grep EXPR,LIST 這種用法差不多了。-f and -T匹配列表裡的元素,首先它必須是個普通檔案,接著它必須是個文字檔。據說這樣寫效率高點哦,因為-T開銷更大,所以在判斷-T前,先判斷-f了。4. 選擇數組元素並消除重複@array = qw(To be or not to be that is the question);@found_words =grep { $_ =~ /b|o/i and ++$counts{$_} < 2; }@array;print "@found_words\n";運行結果是:To be or not to question{}裡的意思就是,對@array裡的每個元素,先匹配它是否包含b或o字元(不分大小寫),然後每個元素出現的次數,必須小於2(也就是1次啦)。grep返回一個列表,包含了@array裡滿足上述2個條件的元素。5. 從二維數組裡選擇元素,並且x<y# An array of references to anonymous arrays@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, 1213, 20這裡,你應該理解匿名數組哦,[]是個匿名數組,它實際上是個數組的引用(類似於C裡面的指標)。@data_points的元素就是匿名數組。例如:foreach (@data_points){print $_->;[0];}這樣訪問到匿名數組裡的第1個元素,把0替換成1就是第2個元素了。所以{ $_->;[0] <$_->;[1] }就很明白了哦,它表示每個匿名數組的第一個元素的值,小於第二個元素的值。而grep { $_->;[0] <$_->;[1] } @data_points; 就會返回滿足上述條件的匿名數組列表。所以,就得到你要的結果啦!6. 簡單資料庫查詢grep的{}複雜程度如何,取決於program可用虛擬記憶體的數量。如下是個複雜的{}樣本,它類比了一個資料庫查詢:# @database is array of references to anonymous hashes@database = ({name    =>; "Wild Ginger",   city    =>; "Seattle",   cuisine   =>;"Asian Thai Chinese Korean Japanese",   expense   =>;4,   music   =>;"\0",   meals   =>; "lunchdinner",   view    =>; "\0",   smoking   =>;"\0",   parking   =>;"validated",   rating   =>;4,   payment   =>; "MCVISA AMEX",},#   { ... }, etc.);sub findRestaurants {my ($database, $query) = @_;return grep {   $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";運行結果是:Wild Ginger上述code不難看懂,但仙子不推薦使用這樣的code,一是消耗記憶體,二是難於維護了。(注,以上內容均源自bbs.chinaunix.net)
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.