1. 程式人生 > >perl字元匹配

perl字元匹配

如果在Unix中曾經使用過sde,awk,grep這些指令的話,相信對於 Perl 語言中的文書處理模式(Regular Expression)應該不會感到陌生才對。在Perl語言中因為有這個功能,所以對於字串的處理能力是非常強有力的。Regular Expression可視為用來處理字串的一種模式(pattern),其使用的格式為/pattern/。在Perl語言的程式中,經常可以看到類似語法的應用,在CGI程式設計中也不例外。只要能夠善用文書處理模式的話,要處理任何難的字串皆可迎刃而解,在本章中筆者會用深入淺出的方式來介紹Regular Expression的用法。

一 文書處理模式中,/pattern/常用到的語法

/pattern/ 結果
除了換行字元\n外,找尋只有一個字元的字串

x? 找尋0個或是1個x字元
x* 找尋0個或是0個以上的x字元
.* 找尋0個或是0個以上的任何字元
x+ 找尋0個或是1個以上的x字元
.+ 找尋1個或是1個以上的任何字元
{m} 找尋剛好是m個個數指定的字元
{m,n} 找尋在m個數個數以上,n個個數以下指定的字元
{m,} 找尋m個個數以上指定的字元
[] 找尋符合[]內的字元
[^] 找尋不符合[]內的字元
[0-9] 找尋符合0到9的任何一個字元
[a-z] 找尋符合a到z的任何一個字元
[^0-9] 找尋不符合0到9的任何一個字元
[^a-z] 找尋不符合a到z的任何一個字元
^ 找尋字元開頭的字元
$ 找尋字元結尾的字元
\d 找尋一個digit(數字)的字元,和[0-9]語法一樣
\d+ 找尋一個digit(數字)以上的字串,和[0-9]+語法一樣
\D 找尋一個non-digit(非數字)的字元,和[^0-9]語法一樣
\D+ 找尋一個non-digit(非數字)以上的字元,和[^0-9]+語法一樣
\w 找尋一個英文字母或是數值的字元,和[a-zA-Z0-9]語法一樣
\w+ 找尋一個以上英文字母或是數值的字元,和[a-zA-Z0-9]+語法一樣
\W 找尋一個非英文字母,數值的字元,和[^a-zA-Z0-9]語法一樣
\W+ 找尋一個以上非英文字母,數值的字元,和[^a-zA-Z0-9]+語法一樣
\s 找尋一個空白的字元,和[\n\t\r\f]一樣
\s+ 找尋一個以上空白的字元,和[\n\t\r\f]+一樣
\S 找尋一個非空白的字元,和[^\n\t\r\f]一樣
\S+ 找尋一個以上非空白的字元,和[^\n\t\r\f]+一樣
\b 找尋一個不以英文字母,數值為邊界的字串
\B 找尋一個以英文字母,數值為邊界的字串
a|b|c 找到符合a字元或是b字元或是c字元的字串
abc 找到一個含有abc的字串
(pattern) ()這個符號是會記憶所找尋到的字元,是一個很實用的語法
第一個()內所找到的字串變成$1這個變數或是\1變數
第二個()內所找到的字串變成$2這個變數或是\2變數
以此類推,筆者會在下一小節中詳細介紹它的用法

/pattern/i i這個引數是代表忽略英文大小寫的意思,也就是在找尋字元 串的時候,不會去考慮英文的大小寫
\ 如果要在pattern模式中找尋一個有特殊的意義的字元,要在 這個字元前加上\這個符號,這樣才會讓這個特殊字元失效

二 文書處理模式(Regular Expression)的簡單範例

看了上一小節文書處理模(Regular Expression)之的,初學者對於這個語法的應用可能還不是很清楚,所以筆者會在這一小節中,舉出一些在文書處理模式中常用的範例給大家看看:

範例 說明
/perl/ 找到含有perl的字串
/^perl/ 找到開頭是perl的字串
/perl$/ 找到結尾是perl的字串
/c|g|i/ 找到含有c或g或i的字串
/cg{2,4}i/ 找到c後面跟著2個到4個g,再跟著i的字串
/cg{2,}i/ 找到c後面跟著2個以上g,再跟著i的字串
/cg{2}i/ 找到c後面跟著2個g,再跟著i的字串
/cg*i/ 找到c後面跟著0個或多個g,再跟著i的字串,如同/cg{0,1}i/
/cg+i/ 找到c後面跟著一個以上g,再跟著c的字串,如同/cg{1,}i/
/cg?i/ 找到c後面跟著0個或是一個g,再跟著c的字串,如同/cg{0,1}i/
/c.i/ 找到c後面跟著一個任意字元,再跟著i的字串
/c..i/ 找到c後面跟著二個任意字元,再跟著i的字串
/[cgi]/ 找到符合有這三個字元任意一個的字串
/[^cgi]/ 找到沒有這三個字元中任意一個的字串
/\d/ 找尋符合數值的字串
可以使用/\d+/來表示一個或是多個數值的字串
/\D/ 找尋符合不是數值的字串
可以使用/\D+/來表示一個或是更多個非數值的字串
/\w/ 找尋符合英文字母,數值的字串
可以使用/\w+/來表示一個或是更多個英文字母,數值的字串
/\W/ 找尋符合非英文字母,數值字元的字串
可以使用/\W+/來表示一個或是更多個非英文字母,數值的字串
/\s/ 找尋符合空白的字串
可以使用/\s+/來表示一個或是更多個空白字元的字串
/\S/ 找尋符合不是空白的字串
可以使用/\S+/來表示一個或是更多不是空白的字元的字串
/\*/ 找尋符合*這個符號的字串,因為*在文書處理模式中有它的特殊意思,所以要在這個特殊符號前加上\這個符號,這樣才會讓這個特殊字元失效
/abc/i 找尋符合abc的字串而且不考慮這些符合字串的大小寫

三 文書處理模式(Regular Expresion)相關的運算子及函式

在perl程式寫作中常會用到=~和!~這兩個運算子及s和t這二個函式來和文書處理模式/pattern/搭配而成一個運算式,如果能夠活用這些指令的話,就可以很。輕易地來處理一些字串,當然在CGI程式設計中了就更能得心應手了。現在就讓作者來介紹這些運算子及函式的用法:

--------------------------------------------------------------------------------

指令:/pattern/文字運算

說明: 如果在文字運算中沒有使用=~或是!~運算子指定一個字串來做運算的話,就會使用內定的輸出變數$_來做/pattern/文字運算。

範例一:

$string="chmod711cgi";
$string=~/(\W)\s+(\d+)/;

第一個(\W+)是********數個字母,並將的找到的字串指派給$1這個變數,而\s+********多個空白的字串,最後(\d+)********個數值,並將所找到的字串指派給$2這個變數。所以$1="chmod";$2=711;但是$string還是等於原來的字串,沒有改變。

範例二:

$_="chmod711cgi";
/(\W)\s+(\d+)/;

因為是把字串指定給$_這個變數,所以可以不用=~這個運算子就會得到

$1="chmod";$2=711;而且$_還是等於原來的字串,沒有改變。

範例三:

$string="chmod711cgi";
@list=split(/s+/,$string);

以上一個或是多個空白字元來分割$string這個字串,這是一個很常用的語法。此時@list=("chmod","711","cgi");

--------------------------------------------------------------------------------

指令: =~相配運算子

說明:這是Perl語言中特有的語法,通常會和文書處理來作運算。

範例:

print"請輸入一個字串!\n";
$string=<STDIN> #<STIDN>********輸入,會讓使用者輸入一字串
chop($string); #將$string最後一個換行的字元\n刪除掉
if($string=~/cgi/){

print("輸入的字串中有cgi這個字串!\n";

}

如果輸入的字串含有cgi這個字串的話,就會顯示出這個資訊。

--------------------------------------------------------------------------------

指令:!~不相配運算子

說明:這也是Perl語言中特有的語法,通常會和文書處理模式來運算。

範例:

print"請輸入一個字串!\n";
$string=<STDIN> #<STIDN>********輸入,會讓使用者輸入一字串
chop($string); #將$string最後一個換行的字元\n刪除掉
if($string!~/cgi/)
{

print("輸入的字串中有cgi這個字串!\n";

}

如果輸入的字串中沒有cgi這個字串的話,就會顯示出這個資訊。

--------------------------------------------------------------------------------

指令:tr轉換函式

語法:tr/SEARCHLIST/REPLACELIST/

其中SEARCHLIST是要轉換的字元;REPLACELIST是轉換成何種字元。

說明:tr(translate)就是轉換的意思,會把符合轉換的字元轉換成要轉換的字元。

範例一:

$string="testing";
$string=~tr/et/ET/"; #此時$string="TEsTing";
$string=~tr/a-z/A-Z/; #此時$stirng="TESTING";

範例二:

$string="CGI+Perl";
$string=~tr/+//; #此時$string="CGI Perl";

在傳送CGI資料的時候會先將資料編碼,其中會將空白的字元轉成+這個字元。

--------------------------------------------------------------------------------

指令:s 取代函式

語法:s/PATTERN/REPLACE/eg

其中

PATTERN是文書處理(Regular Expresion)的模式;
REPLACE是代表取代成何種文字模式。
而g是這個函式最常用的引數,********所有符合文字模式的字串全部取代,如果省略這個引數的話,則只取代一個符合文字模式的字串中;
而加上e這個引數代表要將REPLACE的部分當成一個運算式,如果沒有這個需要的話,就不用加上這個引數了。
說明:將符合文書處理模式的字串取成為要取代的字串

範例一:

$string="i:love:perl";
$string=~s/:/*/; #此時$string="i*love:perl";
$string=~s/:/*/g; #此時$string="i*love*perl";
$string=~s/*/+/g; #此時$string="i+love+perl";
$string=~s/+//g; #此時$string="i love perl";

上一行也可寫成 $string=~tr/+//;效果都會一樣哦!

$string=~s/perl/cgi; #此時$string="i love cgi";

範例二:

$string=~s/(love)/<$1>/;

第一個()內所找到的字串變成$1,在這個範例中,會把變數love這個字串變成<love>,此時$string="i<love>perl";

$string="i love perl";
$string=~s(i)(perl)/<$1><$2>/;

在這個範例中,會把i變成<i>perl變成<perl>,此時$string="<perl> love <i>";

$string="i love perl";
$string=~s(\W+)/<$1>/g;

(/w+)********符合一個或是多個英文字元或是數值的字串,之後再將找到的字串設成$1。因為加上g這個引數,所以會找到字串的這三個英文單字,然後再把這三個單字分加上<>這個符號,此時$string="<perl><love><i>";

範例三:

$string="www22cgi44";
$string=~s/(\d+)/$1*2/e;

(/d+)********尋$string中一個或是多個數值的字串,再將找到的字串設成$1。加上引數e是代表要把$1*2當作是一個運算式,所以$string="www22cgi44";

$string="www22cgi44";
$string=~s/(\d+)/$1*2/eg;

加上引數e,所以會把$1*2當作是一個運算子式來看;加上引數g就會把全部符合數值的字串經過運算式運算之後再把它取代,所以$string="www44cgi88";

範例四:

假設原本的字串是$value="三八!",經CGI資料編碼之後,這個字串就會變成

$value="%A4T%A4K%21"。以下是一個解碼的示範程式:

$value="%A4T%A4K%21";
$vlaue=~s/%([a-fA-F0-9][a-fA-F0-9]/pack("c",hex($1))/eg;

在傳送CGI資料的時候會把資料編碼,其中會將特殊字元或是中文字元編碼以%開頭的連續的兩個十六進位制數的字串,所以要用s這個函式來找尋這個以%開頭的字串。為了要把找到的字串再做解碼的處理,所以要在%這個符號之後加上()這個符號,表示會把找到的字串記憶起來並指定給$1這個變數,而且要在()中加上********續兩個十六進位制數值的文書處理模式(Regular Expression),也就是[a-fA-F0-9][a-fA-F0-9]。再用hex這個函式($1是********的字串)把十六進位制數值轉成十進位制的碼,之後再用pack這個函式(以C為引數,是********gned char value的意思)把這個十進位制碼還原成原來的字串。最後就會把這個字串解碼成$value="三八!"。值得一提的是也可以把這個解碼的程式寫成:

$value=~s/%(..)/pack("C",hex($1))/eg;