[精讚] [會員登入]
727

[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] 命令列傳入參數 argv Perl 的外部傳參,是$ARGV[0]、$ARGV[1]、$ARGV[2].....

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

[PERL] 20- 檔案目錄處理 PERL寫入和讀出檔案

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

PERL 正規表達式會用到的符號 PERL在比對時常常會用到符號整理

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

[PERL]] find 和 perl 的結合--大量檔案中文字的取代 利用PERL作大量的文件取代

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

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

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

我有話要說


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

訪客留言

[無留言]

隨機好文

[大型機台] 熱血高校躲避球 多少少年時光歲月耗在這個遊戲上,二十幾年前的那個時光,唯一想做的事就是把吃飯錢省下來拿去打一場五塊錢的電動,就算是沒錢也

只會買到爛貨的政府採購法 政府採購的公開招標,常常就只能比價格不能比品牌,只能比價格不能比品質,只能比價格不能比口碑,只能比價格不能比信用...

[Mysql/MariaDB] 查看資料庫所占空間 查看資料庫在磁碟中所占空間

[MySQL/Mariadb] console 將查詢結果輸出到檔案 在mysql 的console中該如何將查詢結果輸出到檔案?

原來KNOW-HOW這麼不值啊~~ 我把網路線拔了又插回去,把交換器重開,斷線的問題就解決了,所花的時間30秒..