2013年4月9日 星期二

python regular expression 初探

本編主要是參考 Beginning Python 的 page242頁所寫的
 regular expression 正規表示式 在wiki的介紹

"." 點可以匹配任何字符(除了換行字符外),如'.ython'可以匹配'+ython','kython','python',或' ython'
但是不能匹配'xdython'或'ython',因為"." 只能匹配單一字元,不匹配兩個字元或沒有字元.
因為它匹配任何單一字符(除了換行字符),句號"."又稱為"萬用字元"(wildcard)
"\"跳脫字元,跳脫字元主要用來跳脫一些特殊字元如".",如果我們要匹配'python.org',我們不能用'python.org',這樣會變成匹配'pythonzorg'或'pythonqorg',,,等等的任何一個字元介於python org之間.因為如上所述 "." 是 "萬用字元"會變成匹配任何字元,必須使用'python\\.org',
如果你嫌要打上兩條斜線太麻煩,那可以使用r'python\.org',在兩點前面加一個r,它告訴 python interpreter 這是raw string,你可以少打一條斜線.

character set 字集:如果你要更有效的匹配character( 字符 ) 你可以建立一個character set

(字集) ,使用 [ ] 中括號.

舉例: 

[ pj ]ython將會匹配 python 和 jython.

[a-z]會匹配所有小寫的英文字母.a跟z中間是 -
[a-zA-Z0-9]會匹配大小寫和數字
[^abc]這是指匹配任何字母 "除了 abc ",加上^可用來避開匹配
在[ ]裡如果有 .*,,,等會被regular expression判別為萬用字元的,如果要把它當一般字元還是必須先放 \在前---->[\.\*]

character set 字集可以讓你獨立的匹配字詞,但如果你只是想要匹配 'python' 和 'perl'這兩個字

串呢?你可以使用character set和wildcard設定特定的模式(pattern).
但你也可以使用特殊的字詞來代替:
使用 管線 ' | ',所以你的模式就是 'python|perl'
但如果你不想用一整個詞彙來做模式,你可以使用小括號( )來建立一個子模式(subpattern)
 'python|perl'可以用'p(ython|erl)'來代替.(注意:子模式也可以以單一字詞來用)
"?"在子模式(subpattern)後面增加一個"?",這會讓子模式(subpattern)成為可選擇性的.
舉例:     r'(http://)?(www\.)?python\.org' 會匹配
'http://www.python.org'
'http://python.org'
'www.python.org'
'python.org'
有幾件事是要注意的
\.    使用\去避開wildcards
r'() '    使用raw string去減少 \ 的使用
每個可選擇的子模式被小括號()包括
每個可選擇的子模式也許會出現也許不會,都是各個獨立的.
(pattern)?    問號讓子模式 可以出現一次或無
(pattern)*    星號是重複零次或更多次
(pattern)+    加號是重複一次或更多次
(pattern){m,n}  重複m到n次,如:r'w{3,4}\.python\.org'只匹配'www.python.org' 和 'wwww.python.org'

如果你只想匹配部分字串而不是全部,你可以使用'^'來避開你不想匹配的部分.
舉例: '^ht+p' 會匹配'http://python.org'和'httttttttttttttttttttp://python.org',因為  h 前面使用 ^ 避開了,而 t後面用了 + (加號是重複一次或更多次),所以 t可以一直增加.
python在regular expression 模組裡有建立很多函數可以使用請參考這裡
re.match可以匹配字串中的第一個字

                                       


 re.split 可以拆開一個pattern




如果pattern裡有小括號 parentheses,括號裡的字串將會穿插在其中


maxsplit可以規定要拆的最大範圍

re.findall會回傳所有跟pattern有關的字和標點符號----->findall(pattern, string)
其中[.?\-",]的\-使用\去跳脫-的特殊字符


re.sub( ) 是用來替換  

re.escape( )是用來跳脫字串裡會被當成正規表示式操作符的特殊符號如 " . ",,,等 
使用小括號(parenthesis)去匹配物件:
在小括號內的物件是子模式,又稱為 "團", "group"
group 號是由左至右的.group 0代表整個模式 ,舉例以 下
'My (name is (Joe) (who)) lives (in Taipei City)'
以下是group 括號和號碼的定義
0: My name is Joe who lives in Taipei City
1: name is Joe who
2: Joe
3: who
4: in Taipei City
group 裡也會包括wildcards 或 其它特殊符號,以下

r'www\.(.+)\.org$'

group 0會包含整個字串, group 只會包含介於'www.'和'.org'

一些較重要的方法(method)介紹
start([group])   回傳group開始的點
end([group])     回傳group結束的點
span([group])    回傳group開始和結束的點



以上範例的group位置圖如下
w w w   .   p y t  h o  n    .   o   r    g
0  1  2   3  4 5 6 7 8  9  10 11 12  13
範例的.{3}是指 "." 重複三次 , ". dot "在wildcard裡是字符的意思,所以後面就可以匹配org三個字符.

再來是使用re.sub替換
如果要把*what*變成<em>what<em>話,使用

>>>emphasis_pattern = r'\*([^\*]+)\*'
可以這樣寫
 使用VERBOSE可以讓你加上註解文字.
再來是有關greedy 和 nongreedy patterns
以上範利+這個控制元是預設的"貪心"greedy,所以當替換時會貪心的替換到最大範圍,所以造成中間的*號沒被替換.
所以解決的方式就是+後面再加?號,這樣替換就是"不貪心" nongreedy,以替換範圍裡的最小範圍為主.