顯示具有 chapter 10 - regular expression 正規表示法 標籤的文章。 顯示所有文章
顯示具有 chapter 10 - regular expression 正規表示法 標籤的文章。 顯示所有文章

2011年2月16日 星期三

10 - 1 正規表示-2

在上一個篇幅裡, W簡單的介紹了 search 跟 findall的功能(function),
還有如何使用pattern的概念.如果忘記了, 可以回第一篇復習一下 :)

在這個章節裡, 我們將更深入pattern的內部,了解有哪些regex的關鍵字可以使用,
及相對應的語法.

正規表示(regex)關鍵字:

. 任何字元,數字,符號,及空格
\w 任何字元,數字
\d 任何數字
\s 任何空格
+ 1個或1個以上
* 0個或0個以上

接下來,我們來看看以下的例子.

ex1:
>>> import re
>>> string='abc 123 cde'
>>> pat='..c'
>>> match = re.search(pat,string)
>>> match.group()
'abc'

pat='..c', 指的是找到三個字元,且最後一個字元為c的pattern,
所以會返回一個值, 'abc',
讀者可以試試看,找出開頭為1的pattern,那pat = ?


為了可以簡化流程, W在這裡多加一個功能(function)

def find(pattern, string):
match = re.search(pattern,string)
if match: print match.group()
else: print "not find"

讀者可以藉由這項功能, 不用狂打字, 可以專心練習正規表示的符號.

ex2: (找出開頭為1的pattern)
>>> pat='1..'
或者可以是,
>>> pat = r'\d+'
>>> find(pat,string)
123

pat = r'\d+' 在這個pattern, \d指的是"1"個數字, +加號表達是1個以上的數字,
既然要找的是'123',我們須要有一個以上的數字在我們的pattern之中, 所以要把+加號放在\d的後面, 然後find就會返回一個字串'123'


讓我們再試試看這個例子,

ex3:W把string改成 '1 2 3 123 abc cde', pattern該如何改才可以找到'123'?
>>> string = '1 2 3 123 abc cde'
>>> find(pat,string)
123

因為在'123'前面有三個單獨的數字'1', '2', '3', 很顯然 pat = r'\d+'會match所有的數字,
而我們卻只想要有三個數字黏在一起的'123', 下面是W給的pattern

>>pat = r'\d{3}' , 這樣的寫法表示, 只有三個數字不能多也不能少才是W要的,
然後regex就會去比對,
''1', '2','3'都是單一的數字, 所以不合乎我們的要求, 到了'123', 三個數字,
bingo!找到了黏在一起的'123',
除此之外, W相信大家注意到了, W在單引號(quote)前面放一個'r',
小寫r表示raw string, 意思是python不須要做任何特殊處理的動作,
如果單引號(quote)裡面有遇到反斜線(back slash) "\"!


下面這個例子就是用來解釋raw string,

ex4: 找到".abc"而不是"abc"
>>> string = '.abc 123 abc'
>>> pat = r"\.\w+"
>>> find(pat,string)
.abc

'\.' 的意思是 , 利用反斜線'\'是讓 '.' 原本可以代表任何字元的特殊意思被剔除,
所以'\.'代表的就是符號 點 '.'

再看看下面這個例子,

ex5:找到目錄(directory)路逕
>>> string = r'\home\python\pypyso 123455'
>>> print string
\home\python\pypyso 123455
>>> pat=r'\\\w+\\\w+\\\w+'
>>> find(pat,string)
\home\python\pypyso


'\\'兩個反斜線表示在字串之中找尋一個反斜線,

為什麼使用兩個反斜線呢? 第一個反斜線是用來拿掉反斜線的特殊意義,
所以要在字串裡找尋反斜線符號, 要有兩個反斜線(\\)








10 - 1 正規表示-1

W覺得正規表示法太重要了, 有多重要?

shell script 用不用?

perl 用不用?

Tcl 用不用?

想當然python絕對是不能缺席的!

所以只能說~~太太太重要了!

當讀者需要處理大量的文字訊息, 例如一整個網頁, 一份log, 逐字逐句的看嗎?

100行以內可能還可以辦到, 倘若1000000行, 或甚至更多的時候, 該怎麼辦?

好在, 早就有人發現了這個問題, 發明了regular expression (正規表示),

它的好處是可以處理掉讀者不想閱讀的部份, 或是過濾掉不必要的訊息,

只清楚地顯示你所需要的那一部份..


這樣解釋或許有點讓人不清楚, 讓我們看看以下的例子


在python之中, 要使用regular expression (簡稱regex), 只要import re這個模組,

ex1:
>>> import re
>>> pat='abc'
>>> string='123 abc'
>>> match = re.search(pat,string)
>>> match.group()
'abc'
>>>

在例子1當中,
1. 我們import re, re指的就是正規表示(regex)
2. 定義了要檢查的樣式(pattern), pat = 'abc', 意思是要找含有'abc'的樣式
3. string = '123 abc' 指的是將被搜尋的字串
4. 定義了match, 指的是如果正規表示找到了含有abc的字串, 把結果存入match這個物件(object)之中
5. re.search(patter,string), 當使用 re的search功能, 第一個需要放入檢驗用的樣式(pattern), 第二要放入將被搜尋的字串(string)
6. 透過 match.group()可以顯示出找到的字串

讓我們再看看下一個例子
ex2:
>>> string='123 abc abc abc'
>>> match = re.search(pat,string)
>>> match.group()
'abc'
>>>

在這, 我們可以發現search, 只會配對一次, 就算後面還有也不會處理,
所以match.group()只會單單顯示一個結果,
那如果我們想要找到所有的結果呢?

python 當然早就準備好囉!請看下面一個例子,

ex3:
>>> match = re.findall(pat,string)
>>> match
['abc', 'abc', 'abc']

我們在這用了 findall(), 用法跟search 十分相似, 也需要給pattern跟string.
,然後結果會返回一個串列(list), 如上所示.找到了三組'abc'

應該比想像中簡單吧? 在讓我們實驗一下下面這個例子,

ex4:
>>> pat = 'cde'
>>> match = re.search(pat,string)
>>> match
>>> type(match)

>>> match.group()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'NoneType' object has no attribute 'group'
>>>

1. 在這個例子, W把pat換成'cde', 當然會在string找不到配對成功的結果,
2. match這個物件(object)變成None, 因為re.search()找不到所以返回(return)一個空值(None)
3. W順便利用一下type(), 來檢驗一下match這個物件(object)的形態
4. 如上所示, type 是空值
5. 所以match.group()會有錯誤訊息告訴讀者, 沒有group這個屬性(attribute)

經過上面幾個例子的練習, W想大家應該對re摸組的search跟findall有一定的認識了,



不過老實說,

W還沒開始介紹真正的正規表示(regex), 嘿嘿~

其實正規表示指的是利用某些通用的符號或是正規表示的關鍵字, 達到處理字串的效果.

在正規表示的一開始, 總要先瞭解一下有那些function可以使用, 該怎麼用, 然後再來學習regex,

各位看官您說是吧?


在下一個篇幅, W就要正式切入正規表示法囉, 請務必練習一下上面的例子!