[精讚] [會員登入]
5254

[PERL] 14-進階比對 #1--取回比對內容

perl的正規表達式進階比對

分享此文連結 //n.sfs.tw/11715

分享連結 [PERL] 14-進階比對 #1--取回比對內容@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2019-10-25 14:07:12 最後編修
2017-08-27 10:02:23 By 張○○
 

自動目錄

04-基本比對中有提過了基本的比對,此篇更深入一點。

取回比對的內容

如果想取得比對的結果,使用小括號 '()',取回符合的內容用 $1, $2, $3, ...:

舉例而言,如果我們想要取回 email 中的@前面的username和@後面的domain name:

$email = "server\@n.sfs.tw";
$email =~ /([^@]+)\@(.+)/;
print $1; # server
print $2; # n.sfs.tw
print $&; # server@n.sfs.tw

  $email 是被比對的變數,注意這裡的@前面有一個脫逸字元'\',是因為@在雙引號字串中會被當成陣列,所以一定要加上,如果是單引號字串 就不必加。
  =~ 符合比對運算子
  /([^@]+)\@(.+)/ 比對的樣式說明如下
   () 小括號中的內容是要取出符合的內容
     [] 中括號是符合其中字元的集合
       ^@ 在中括號一開始加上這個符號代表是「否定」的意思,全部的意思是只要不是 '@'都行
       + 代表出現1個以上
      \@ 因為在樣式裡面也是能放變數,所以前面加上脫逸字元'\'來確保要比對的是符號'@',如果沒加'\',PERL會判斷這個陣列變數是否存在,有存在就會置換成該變數;不存在時就當成是一般字元處理,有時也許會造成錯誤。
   () 小括號中的內容是要取出第二個符合的內容
     . 代表任一個字元
       + 代表出現1個以上 

因此如果$email符合比對的樣式,第3行和第4行用特殊變數 $+數字依序取回符合的內容。

PERL用 $1, $2, $3, $4....是以小括號的左邊出現次序,依序取回符合的內容。
$& 代表比對成功的部分,這是PERL的特殊變數。

另外,
$` 代表比對到的字串之前半段所有字串
$' 代表比對到的字串之後半段所有字串

 例如我們取出IP中每個字節的數字

$ip='211.75.194.243:8080';
$ip=~ /((\d+)\.(\d+)\.(\d+)\.(\d+)):(\d+)/;

print "$1, $2, $3, $4, $5, $6\n"; # 211.75.194.243, 211, 75, 194, 243, 8080

可以看到 $1是第一個左括號的範圍。

上面的程式要做一點調整,因為有時比對不成功的話 $1 = $2 = $3 = ... = '' 會是空字串,必須加上判斷

$ip='AAA.75.194.243:8080';
if($ip=~ /((\d+)\.(\d+)\.(\d+)\.(\d+)):(\d+)/){
  print "$1, $2, $3, $4, $5, $6\n";
}else{
  print "比對失敗\n";
}

這樣就能做錯誤控制。

取回比對的內容同時也加入比對

有時我們需要把比對成功的字串同時再比對,例如要找出有連續字元的單字,例如 look, snoop, peer, employee 符合條件。

這時就需要用到特殊變數 \1, \2, \3, ...,和$1, $2, $3不同的地方在於它們只能放在樣式之中,來看看範例。

@words= qw ( usually positive floor flee eels country );

foreach(@words){
  if( $_ =~ /([a-z])\1/ ){
    print $_. "\n";
  }
}

第4行 利用\1將第一個比對符合的小括號再次比對,來檢查重覆出現的字元。

結果

usually
floor
flee
eels

整篇文章中的文字搜索

上面學到了怎麼取出具有重覆字元的單字,如果是整篇文章要取資料。來看範例:

$doc=<<"DOC";
       If  FIRST or INCREMENT is omitted, it defaults to 1.  That is, an omitted INCREMENT defaults to 1 even when LAST is smaller than
       FIRST.  The sequence of numbers ends when the sum of the current number and INCREMENT would become greater  than  LAST.   FIRST,
       INCREMENT,  and LAST are interpreted as floating point values.  INCREMENT is usually positive if FIRST is smaller than LAST, and
       INCREMENT is usually negative if FIRST is greater than LAST.  FORMAT must be suitable for printing one argument  of  type  'dou‐
       ble';  it defaults to %.PRECf if FIRST, INCREMENT, and LAST are all fixed point decimal numbers with maximum precision PREC, and
       to %g otherwise.

       GNU coreutils online help: <http://www.gnu.org/software/coreutils/>  Report  seq  translation  bugs  to  <http://translationpro‐
       ject.org/team/>
DOC

while($doc =~ /[\w]*([\w])\1[\w]*/g){
  print $&. "\n";
}

第1行 $doc只是一篇文章
第13行 樣式是 /[\w]*([\w])\1[\w]*/g 說明如下

  [\w]* \w代表[a-zA-Z_0-9]這些字元,有出現0個字元以上,當出現0個時,重覆字元會在單字面出現。
   () 小括號中的內容是要取出符合的內容
      [\w]+ 小號內代表有1個字元以上
   \1 當第1個小括號比對符合時,再拿來比對,表示連續出現的字元
  [\w]*代表\w出現0個字元以上,當出現0個時,重覆字元會在單字面出現。

第14行是印出全部比對的範圍。

在樣式的最後面有一個字元 'g' ,這並不是打錯,而是稱之為「修飾子」的字元,這算是一個比對位置指標,下次的比對會從上一次比對符合的目標下一個字元找起。千萬不能省略這個g,省略的話會掉入無窮迴圈中。有關於更多修飾子的內容會在下一篇說明。

結果

omitted
omitted
smaller
current
usually
smaller
usually
all
http
www
http

有人會問,如果把第13行改成

while($doc =~ /([\w])\1/g){

不就剛好能找出兩個連續的字元了嗎,為什麼還有多旁邊的 [\w]* ,理由很簡單,因為那樣的輸出結果會是:

tt
tt
ll
rr
ll
ll
ll
ll
tt
ww
tt

你不會知道那是什麼字。

上一篇 13- 變數的視界
回到目錄 01-撰寫第一隻PERL程式
下一篇 15-進階比對 #2--使用更多修飾子

END

你可能感興趣的文章

Perl 的特殊變數:$_、$&、$! 介紹perl的特殊變數 $_ 、 $&、$!

[PERL] 用substr切割及置換字串 perl用substr來切割及置換字串

[PERL] 常態分配亂數產生函數 一般而言我們使用程式內建的 rand 函數取得的亂數是平均分配的,但如果需要常態分配的亂數產生器該怎麼做?

Apache Worker MPM =worker 調整參數 Apache目前一共有三種穩定的MPM(Multi-Processing Module,多進程處理模式 簡稱: MPM)

PERL一次讀取檔案所有內容的方法($/) perl可以使用slurp mode一次讀完檔案所有內容的方法及一些範例

[PERL] 24-呼叫系統程式及評估 Perl 如何呼叫系統程式並取回結果?

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

[jQuery] 利用load()來達成ajax的寫法 jQuery中利用load()來達成ajax的寫法,也有人稱他是假的ajax,作法就是..

[jQuery] textarea 的取值和給值 HTML 的 TEXTAREA 標籤若要用 jquery 取值,不能使用 .text() 或 .html() ,使用 .

UTF-8 BOM (Byte Order Mark) 的問題 在 Michael Kaplan 那看到 Every character has a story #4: U+feff

[Windows7] 移除IE10及移除IE11 Windows7 不得已的情況要移除IE11或IE10怎麼做?

為什麼要重造輪子? 什麼輪子?造什麼輪子?我為什麼要重造輪子?