[精讚] [會員登入]
562

[PERL] 15-進階比對 #2--使用更多修飾子

perl的正規表達式進階比對

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

複製連結 [PERL] 15-進階比對 #2--使用更多修飾子@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2018-01-03 02:06:01 最後編修
2017-09-20 16:46:09 By 張○○
 

在前面有提到過樣式後面的修飾子 'g',接下來深入探討更多的修飾子。

不分大小寫比對

使用 'i' 修飾子可以在比對時忽略大小寫,i是ignore的意思,這個只會忽略英文字母的大小寫。

$str = "When and how is John doing?";
if( $str =~ /when/i ){
  print $& ."\n"; #When
}

第2行 多了一個 i作修飾子,所以 When會和when比對成功並傳回'When'

 

中文字的比對

中文字的比對和非中文的比對相同,可以直接把中文字串放入即可,perl會自動判斷編碼,沒什麼問題。若要強調比對 utf-8編碼(其實是unicode)的話,可以加上 'u' 或是 'a' 的修飾子,這兩個的差異僅在於 'a'會把ascii的字元就視為ascii的字元,而不會再轉成unicode比對 [1]

$str = "這場探討未來網路發展的世界級會議,最近剛於瑞士日內瓦落幕。
會議中,除了討論美國政府最近收回網路中立成規的決定,
對數位媒介演進太過迅速,可能造成保存問題的憂慮。";
if( $str =~ /數位媒介/a ){
  print $& ."\n"; # 數位媒介
}

第1~3行 這個字串分成三行,在每個行尾都有隱藏的 '\n'字元
第4行 使用了a修飾子指定把除了ascii的字元外的字元都視為unicode字元。

由於PERL會自動判斷編碼,事實上就算省略了這個a也能正確的判斷,但為了避免不必要的意外,遇到中文字還是建議加上。

 

比對的內容含有換行時,把換行也考慮進來

在上面的範例中,字串可能因為換行的關係而切斷,在比對時就會被忽略導致非預期的結果,舉例來說,下面字串中「網路」兩個字可能因為文章的寬度緣故被拆成兩行,實際上網路兩字中間還多了一個換行\n的符號:網\n路

$str = "這場探討未來
發展的世界級會議";

假設我們拿來比對字串「網路」,就會發現比對失敗。為了增加比對的正確性,比對時也要把可能被拆開的字串進行判斷:

$str = "這場探討未來網
路發展的世界級網路會議";
if( $str =~ /網\n?路/a){
  print $& ."\n";
}

第3行 比對字串中網路兩字中間加了一個\n?,代表判斷換行的有無。

結果


中文字麻煩的地方,也可以說是方便的地方,就是可以斷在任何地方,如果是二個字的詞就只有一種斷法,三個字的詞就會有三種斷法,n個字的詞就會有2(n-1)-1種斷法,比較偷懶的比對就是把所有的換行都先置換掉再來比對,缺點是內容很長會不知道這到底是原文的哪裡?因為換行都被抽掉,位置是抽掉後的結果。不然就是每個字和字中間都加上'\n?' 來作樣式,因為這是門困難的科學,所以略過不提。

 

一個unicode中文字代表三個字元

中文字的比對要注意,一個unicode中文字代表三個字元,例如:

$str = "這場探討未來長頸鹿存活的會議";
if( $str =~ /長.鹿/a){ print "比對成功"; }

在這範例中是不會比對成功的,除非你把'.'改成'.{3}'

if( $str =~ /長.{3}鹿/a){ print "比對成功"; }

 

把換行視為一個字元

使用 's' 修飾子可以在比對時把換行也當成一個字元來處理,沒有加s的話,比對任何一個字元 '.' 會忽略換行。

$str = "John is a boy, Mary is
a girl. They are friends.";
while( $str =~ /is.a/sg){
  print $& ."\n";
}

說明

第3行 修飾子用's'讓換行可以比對成功,在while中要加入修飾子'g'以免造成無窮迴圈。

結果

is a
is
a

如果上面沒加上 修飾子's',比對出來結果只會有一個:

is a

把字串視為多行來比對

使用 'm' 修飾子可以在比對時把換行也當成一個字元來處理,這對多行的文比對很有用。這時候代表開始的記號'^'和結束的記號'$'就會判斷每一行的頭和尾,如果沒加m的話,就只會判斷一開始和結束。

$str = "Sweater costs 200 dollars
Shirt is 300 dollars
Pants are 400
Stockings are 100 dollars";

while( $str =~ /\d+ dollars$/g){
  print $& ."\n";
}

結果

100 dollars

上面的例子中,因為在樣式中比對出行尾有 "數字 dollars"的內容,所以會把整個字串中的換行算成字串的一部分。

如果加上了 'm' 修飾子,在判斷時就會每個換行都當成一行來判斷,同樣的,在while中要加入修飾子'g'以免造成無窮迴圈。

while( $str =~ /\d+ dollars$/mg){

結果

200 dollars
300 dollars
100 dollars

Perl的修飾子很多,剩下的到取代章節再來談。

上一篇 14-進階比對 #1--取回比對內容
回到目錄 01-撰寫第一隻PERL程式
下一篇 16-字串取代和置換

參考資料

[1] https://perldoc.perl.org/perlre.html

你可能感興趣的文章

[PERL] 07-陣列 #1 -- 基本 perl的陣列

[PERL] 19-模組的安裝和維護 模組的安裝和維護

[PERL] 04-基本比對 perl的正規表達示基本比對

[PERL] 簡易檢查網頁記錄檔ip來源統計 利用PERL來檢查網頁記錄檔ip來源統計的簡易程式

[PERL] 06-運算子 #2 PERL的運算子介紹,總共有21種

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

[PERL] 03-條件式判斷 perl的條件式判斷

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

[PERL] 14-進階比對 #1--取回比對內容 perl的正規表達式進階比對

[PERL] 09-迴圈 perl的迴圈

我有話要說


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

訪客留言

[無留言]

隨機好文

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

[Freebsd] 使用 ADSL 撥接上網 Freebsd上要使用 ADSL 撥接上網,該如何設定?

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

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

[MAC] 安裝APACHE+PHP OS Darwin OpenIDMac1deAir 15.6.0 Darwin Kernel Version 15.6.