perl中grep的詳細用法

最近一直在學習perl語言,下面介紹下若是和在perl編程中使用強大的grep函數。正則表達式

1. Grep函數
grep有2種表達方式:編程

1 grep BLOCK LIST
2 grep EXPR, LIST

 

BLOCK表示一個code塊,一般用{}表示;EXPR表示一個表達式,一般是正則表達式。原文說EXPR但是任何東西,包括一個或多個變量,操做符,文字,函數,或子函數調用。
LIST是要匹配的列表。
grep對列表裏的每一個元素進行BLOCK或EXPR匹配,它遍歷列表,並臨時設置元素爲$_。在列表上下文裏,grep返回匹配命中的全部元素,結果也是個列表。在標量上下文裏,grep返回匹配命中的元素個數。
2. Grep 和 loops數組

1 open FILE "<myfile"ordie"Can't open myfile: $!";
2 print grep /terrorism|nuclear/i,<FILE>;

 

這裏打開一個文件myfile,而後查找包含terrorism或nuclear的行。<FILE>返回一個列表,它包含了文件的完整內容。可能你已發現,若是文件很大的話,這種方式很耗費內存,由於文件的全部內容都拷貝到內存裏了。
固然你也能夠使用loop(循環)來完成:app

1  while($line =&lt;FILE&gt;;){
2     if($line =~/terrorism|nuclear/i){print $line }
3     }

 

上述code顯示,loop能夠完成grep能作的任何事情。那爲何還要用grep呢?答案是grep更具perl風格,而loop是C風格的。
更好的解釋是:(1)grep讓讀者更顯然的知道,你在從列表裏選擇某元素;(2)grep比loop簡潔。
一點建議:若是你是perl新手,那就規矩的使用loop比較好;等你熟悉perl了,就可以使用grep這個有力的工具。
3.幾個grep的示例
函數

1. 統計匹配表達式的列表元素個數工具

 

$num_apple = grep /^apple$/i,@fruits;

 

 

 

在標量上下文裏,grep返回匹配中的元素個數;在列表上下文裏,grep返回匹配中的元素的一個列表。
因此,上述code返回apple單詞在@fruits數組中存在的個數。由於$num_apple是個標量,它強迫grep結果位於標量上下文裏。oop

2. 從列表裏抽取惟一元素學習

1 @unique= grep {++$count{$_}&lt;2}
2 qw(a b a c d d e f g f h h);
3 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次的抽取元素了。ui

2. 抽取列表裏精確出現2次的元素spa

1     @crops= qw(wheat corn barley rice corn soybean hay
2     alfalfa rice hay beets corn hay);
3     @duplicates= grep { $count{$_}==2}
4     grep {++$count{$_}&gt;;1}@crops;
5     print"@duplicates\n";

 

運行結果是:rice
這裏grep了2次哦,順序是從右至左。首先grep { ++$count{$_} >; 1 } @crops;返回一個列表,列表的結果是@crops裏出現次數大於1的元素。
而後再對產生的臨時列表進行grep { $count{$_} == 2 }計算,這裏的意思你也該明白了,就是臨時列表裏,元素出現次數等於2的被返回。
因此上述code就返回rice了,rice出現次數大於1,而且精確等於2,明白了吧? 

3. 在當前目錄裏列出文本文件

1     @files= grep {-f and-T } glob '* .*';
2     print"@files\n";

 

glob返回一個列表,它的內容是當前目錄裏的任何文件,除了以’.'開頭的。{}是個code塊,它包含了匹配它後面的列表的條件。這只是 grep的另外一種用法,其實與 grep EXPR,LIST 這種用法差很少了。-f and -T 匹配列表裏的元素,首先它必須是個普通文件,接着它必須是個文本文件。聽說這樣寫效率高點哦,由於-T開銷更大,因此在判斷-T前,先判斷-f了。

4. 選擇數組元素並消除重複

1     @array= qw(To be ornot to be that is the question);
2     @found_words=
3     grep { $_ =~/b|o/i and++$counts{$_}&lt;2;}@array;
4     print"@found_words\n";
5      

 

運行結果是:To be or not to question
{}裏的意思就是,對@array裏的每一個元素,先匹配它是否包含b或o字符(不分大小寫),而後每一個元素出現的次數,必須小於2(也就是1次啦)。
grep返回一個列表,包含了@array裏知足上述2個條件的元素。

5. 從二維數組裏選擇元素,而且x<y

1     # An array of references to anonymous arrays
2     @data_points=([5,12],[20,-3],
3     [2,2],[13,20]);
4     @y_gt_x= grep { $_-&gt;;[0]&lt; $_-&gt;;[1]}@data_points;
5     foreach $xy (@y_gt_x){print"$xy-&gt;;[0], $xy-&gt;;[1]\n"}

 

運行結果是:
5, 12
13, 20
這裏,你應該理解匿名數組哦,[]是個匿名數組,它其實是個數組的引用(相似於C裏面的指針)。
@data_points的元素就是匿名數組。例如:

1     foreach(@data_points){
2     print $_-&gt;;[0];}

 

這樣訪問到匿名數組裏的第1個元素,把0替換成1就是第2個元素了。
因此{ $_->;[0] < $_->;[1] }就很明白了哦,它表示每一個匿名數組的第一個元素的值,小於第二個元素的值。
而grep { $_->;[0] < $_->;[1] } @data_points; 就會返回知足上述條件的匿名數組列表。

參考:perl語言學習

相關文章
相關標籤/搜索