[精讚] [會員登入]
1018

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

perl的正規表達式進階比對

此文完整連結 http://n.sfs.tw/11715

複製連結 [PERL] 14-進階比對 #1--取回比對內容@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2018-01-02 22:53:02 最後編修
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--使用更多修飾子

你可能感興趣的文章

[PERL] 命令列傳入參數 argv Perl 的外部傳參,是$ARGV[0]、$ARGV[1]、$ARGV[2].....

[PERL] 中文字字串拆解 中文字字串拆解是門學問

[PERL] 18-套件及模組 套件和模組入門

[PERL] 檢查IP是否在某個網段內:matchcidr 檢查IP是否在某個網段內 matchcidr in perl

[PERL] 02-註解、變數和常數 perl的註解、變數和常數

[PERL] 12- 副程式 Perl 的副程式就是所謂的函數

[PERL] 前置if和後置if (if修飾子)的差別 perl的if可以拿來作為後置修飾子使用,此外還有一個unless像是if的相反,分析他們的差異

[PERL] 21- 使用資料庫 Perl 連Mysql

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

自行撰寫syslog server建立資訊安全控管中心#3 -- 程式下載和安裝 利用PERL將syslog收攏到資料庫的程式,程式下載和安裝

我有話要說


限制:留言最高字數1000字,超過部分會被截掉。請注意:留言不可帶有網址,會被濾掉。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

為什麼要買長達二十年的保單? 為什麼要買長達二十年的保單?找一個可以說服我買二十年保單的理由。

Linux shell 的date表示法 linux下SHELL中的date表示法

[AS3] 我做的唯一一個Flash As3遊戲UFO INVADSION [AS3] 我做的唯一一個Flash As3遊戲,是第一個也是最後一個,後來就沒再寫as3,不過as3還滿好玩的。

[CodeIgniter 3] 資料庫的使用方法整理2/2 CI3 承襲 CI2,有很多的builder class可以用,依各人的使用習慣,有人喜歡一堆sql字串,有人喜歡用helper

問問題 問問題其實內涵很深,我悟了很久才懂。 有人問題的目的並不一定是想要得到答案,有時只是純粹想問問題..