顯示具有 正規表示式 標籤的文章。 顯示所有文章
顯示具有 正規表示式 標籤的文章。 顯示所有文章

2009年8月11日 星期二

正規表示式2

引用 http://fannys23.pixnet.net/blog/trackback/e150b26b3d/15367167


檢查工具 http://osteele.com/tools/rework/

1. 對正規表示式來說,任意字元是以點 (.) 表示。
e.g.
a...e 表示 a 與 e 之間有任意三個字元
ae←比對失敗
a12e←比對失敗,因為不足三個字元
abcde←比對成功

2. 中括號中表示指定特定的字元,若其中一個符合則符合
e.g.
a[abc]e
比對成功的例子: aae, abe, ace
比對失敗的例子: aze

3. 小寫的檢查: a-z,大寫的檢查: A-Z,數字的檢查: 0-9
e.g.
a[0-9a-zA-Z]e
在 a 與 e 間插入多個英數字或插入一個以上的特殊符號外,其他都符合規則

4. 在中括號之中的點 (.) ,僅代表一個點。
e.g.
a[.]e
只有 a.e 符合

5. 符號 ^ 在第一個字元出現時有 not 的意思
e.g.
a[^0-9a-zA-Z]e 表示英數字以外的符號符合此項比對

6. 符號 ^ 在第一個字元以外的地方出現,代表 ^ 本身這個字
e.g.
a[0-9^a-zA-Z]e 表示 a 和 e 間出現一個 ^ 或一個英數字均符合

7. 修飾詞:
星號 (*) 可用來代表零或多個
e.g.
a.*z 若字詞頭為 a 尾為 z 則符合
ab*z 若字詞頭為 a 尾為 z ,且中間出現一個以上的 b 則符合
ab.*z 字詞頭為 ab 尾為 z 則符合

問號 (?) 代表零個或一個
w.?e
符合的範例:we、wie
不符合的範例:willie

加號 (+) 代表一個或多個
e.g.
a.+z 在 a 和 z 之間出現一個或以上的字元即符合

若希望在 a 與 z 之間有一個以上非英文大寫的任意字元,
寫法為: a[^A-Z]+z

8. 大括號用來精確比對前一個字
ab{5}z ←僅 abbbbbz 符合
ab{1,5}z ←表示 b 出現最少一次、最多五次
a[A-Z]{1,5}z ←中間可以有一到五個大寫英文字

9. 意義相同的正規表示式:
b{1,} = b+
b{0,} = b*

10. 逸出字元前要加上反斜線
a\.b
a\[b
a\\b

11. 群組(grouping): 用小括號包起來
a(abc)*z ←表示 a 開頭、z 結尾,中間出現任意次數的 "abc"
另外也有記憶小括號的功能
e.g.
import re
m = re.search('it is (fine (today))', 'it is fine today')
m.group(0)
m.group(1)
m.group(2)
#以上程式會依續印出完整字串、左起第一組小括號、第二組小括號

12. 較短的表示方式:
http://www.amk.ca/python/howto/regex/
\w = [a-zA-Z0-9_]
\s = [\t\n \r\f\v]
\d = [0-9]      ←所以 IP 比對可以改寫成 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
            還可以再縮寫成 \d{1,3}(\.\d{1,3}){3}

大寫則有反義的用途,
例如 \D 是非數字,\W 代表非英數字、\s 代表非空白字元

13. 字和空白之間的交會點是 \b
因此 "Will and Willie are good friends."
可以利用 Will\b 找出 Will (以免同時也比對到 Willie)

14. 正規表示式預設有「貪多」的特性
import re
reg = re.search("t.*d", "today is fine")
reg.group()

這樣的搜尋會一路找到結尾、再找回來、才取出 tod,
會造成效能上的耗費,因此有不貪多演算法,
\.*? ←代表抓取任意字元、任意次數、不貪多
\.+? ←代表抓取任意字元、一次以上、不貪多

不貪多演算法的說明
http://www.gais.com.tw/article.php?u=DeeR&i=20080225

15. 把沒有明顯分隔符號的字串切割重組
e.g.
import re
text = "willie123good456"
"".join(re.split(r"\d+", text))

16. 使用其他人寫好的套件剖析 XML 與 HTML

HTML:
Beautiful Soup
http://www.crummy.com/software/BeautifulSoup/

Parsing HTML 的說明
http://www.crummy.com/software/BeautifulSoup/documentation.html#Parsing%20HTML

XML:
ElementTree
http://effbot.org/zone/element-index.htm
Parsing XML 的說明
http://docs.python.org/lib/module-xml.etree.ElementTree.html



【實作練習: 剖析 log 中異常的 IP】
#假設 IP 為 200 開頭的是異常 IP
#!/usr/bin/python

import re
f = open('/tmp/auth.log')
for i in f:
regex = re.search(r'200\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', i)
if regex:
print regex.group()
f.close()

#re.search 表示比對正規表示式與輸入結果
#第一個參數是正規表示式,第二個是輸入內容
#regex.group() 預設參數是 0

tips:
小括號包起來的東西在 python 裡會被記憶,
因此若只想取 ip 最後一段,可改寫如下:

import re
f = open('/tmp/auth.log')
for i in f:
regex = re.search(r'200\.[0-9]{1,3}\.[0-9]{1,3}\.([0-9]{1,3})', i)
#加上小括號
if regex:
print regex.group(1)
#加上小括號所出現的 index (從 1 開始算)
f.close()



【實作練習:分析 log 檔中的非法使用者想入侵的帳號】

#!/usr/bin/python

import re
f = open('/tmp/auth.log')
for i in f:
regex = re.search(r'Invalid user ([^ ]+) from ([^ ]+)', i)
if regex:
print regex.group(1) + " => " + regex.group(2),
f.close()



【實作練習:分析 log 檔中的非法使用者想入侵的帳號 (改善執行效能)】

#!/usr/bin/python

import re
f = open('/tmp/auth.log')
rec = re.compile(r'Invalid user ([^ ]+) from ([^ ]+)')
for i in f:
regex = rec.search(i)
if regex:
print regex.group(1) + " => " + regex.group(2),
f.close()



【實作練習:分析 log 檔中的非法使用者想入侵的帳號 (縮短正規表示式)】

#!/usr/bin/python

import re
f = open('/tmp/auth.log')
rec = re.compile(r'Invalid user (\w+) from ([^ ]+)')
for i in f:
regex = rec.search(i)
if regex:
print regex.group(1) + " => " + regex.group(2),
f.close()



【實作練習:取出 HTML 的部分內容】

from BeautifulSoup import BeautifulSoup
f = open('test.htm')
html = f.read()
f.close()
soup = BeautifulSoup(html)
soup.html.body.span.string         #取出span標籤內夾記的內容
soup.html.body.a.string          #預設會取出第一個找到的 a 標籤夾記的內容
soup.html.body('div')[1].a.string     #取得第二組 div 內的 a 標籤
soup.html.body.div.a['href'] #抓出 a 標籤中的屬性 href



【實作練習:取出 XML 的部分內容】(for python 2.5)

from xml.etree.ElementTree import XML
myxml = open('test.xml').read()
seek = XML(myxml)
seek.getchildren() #確認 seek 可找到哪些子節點
seek.find('staff').find('name').text #取出子節點 staff 中的 name 裡頭的內容
for i in seek.findall('staff'): #找出所有的 staff
print i.find('name').text #取出 staff 中的 name 內容

正規表示式1 regular expressions


出處 http://osteele.com/tools/rework/

For more information about how to use regular expressions, including examples, additional documentation, and additional tools, see:
Regular-Expressions.info (online)
RegExLib (online)
Jeffrey Freidl's Mastering Regular Expressions (Amazon)

Quick Reference:
. any character except newline. If DOTALL, matches newline.
^ the start of the string. In multiline, matches start of each line.
$ the end of the string or just before the last newline. In multiline, matches before each newline.
\d,\w,\s digit, word, or whitespace, respectively
\D,\W,\S anything except digit, word, or whitespace
\. a period (and so on for \*, \(, etc.)
[ab] characters a or b
[a-c] a through c
[^ab] any character except a or b
expr* zero or more repetitions of expr
expr+ one or more repetitions of expr
expr? zero or one repetition of expr
*?,+?,?? ...same as above, but as little text as possible
expr{m} m copies of expr
expr{m,n} between m and n copies of the preceding expression
expr{m,n}? ...but as few as possible
a|b either a or b
(expr) same as expr, but captures the match for use in \1, etc.
(?:expr) doesn't capture the match
(?=expr) followed by expr
(?!expr) not followed by expr