在平常工做中常常碰見在文本中提取特定位置字符串的需求.python的正則性能好,很適合作這類字符串的提取,這裏講一下提取的技巧,正則表達式的基礎知識就不說了,有興趣的能夠看re的教程. 提取通常分兩種狀況,一種是提取在文本中提取單個位置的字符串,另外一種是提取連續多個位置的字符串.日誌分析會遇到這種狀況.下面我會分別講一下對應的方法:python
這種狀況咱們可使用(.+?)
這個正則表達式來提取. 舉例,一個字符串"a123b"
,若是咱們想提取ab之間的值123,可使用findall
配合正則表達式,這樣會返回一個包含因此符合狀況的list,代碼以下:web
import re str = "a123b" print re.findall(r"a(.+?)b",str)# 輸出['123']
若是咱們有一個字符串」a123b456b」,若是咱們想匹配a和最後一個b之間的全部值而非a和第一個出現的b之間的值,能夠用?
來控制正則貪婪和非貪婪匹配的狀況. 代碼以下:正則表達式
import re str = "a123b456b" print re.findall(r"a(.+?)b", str) #輸出['123']#?控制只匹配0或1個,因此只會輸出和最近的b之間的匹配狀況 print re.findall(r"a(.+)b", str) #輸出['123b456'] print re.findall(r"a(.*)b", str) #輸出['123b456']
若是你要多行匹配,那麼須要加上re.S
和re.M
標誌. 加上re.S
後, .
將會匹配換行符,默認.
不會匹配換行符. 代碼以下:api
str = "a23b\na34b" re.findall(r"a(\d+)b.+a(\d+)b", str) #輸出[] #由於不能處理str中間有\n換行的狀況 re.findall(r"a(\d+)b.+a(\d+)b", str, re.S) #s輸出[('23', '34')]
加上re.M
後,^$
標誌將會匹配每一行,默認^
和$
只會匹配第一行. 代碼以下:性能
str = "a23b\na34b" re.findall(r"^a(\d+)b", str) #輸出['23'] re.findall(r"^a(\d+)b", str, re.M) #輸出['23', '34']
這種狀況咱們可使用(?P<name>…)
這個正則表達式來提取. 舉例,若是咱們有一行webserver的access日誌:'192.168.0.1 25/Oct/2012:14:46:34 "GET /api HTTP/1.1" 200 44 "http://abc.com/search" "Mozilla/5.0"'
,咱們想提取這行日誌裏面全部的內容,能夠寫多個(?P<name>expr)
來提取,其中name能夠更改成你爲該位置字符串命名的變量,expr改爲提取位置的正則便可. 代碼以下:spa
import re line ='192.168.0.1 25/Oct/2012:14:46:34 "GET /api HTTP/1.1" 200 44 "http://abc.com/search" "Mozilla/5.0"' reg = re.compile('^(?P<remote_ip>[^ ]*) (?P<date>[^ ]*) "(?P<request>[^"]*)" (?P<status>[^ ]*) (?P<size>[^ ]*) "(?P<referrer>[^"]*)" "(?P<user_agent>[^"]*)"') regMatch = reg.match(line) linebits = regMatch.groupdict() print linebits for k, v in linebits.items() : print k+": "+v
輸出的結果爲:日誌
status: 200
referrer:
request: GET /api HTTP/1.1
user_agent: Mozilla/5.0
date: 25/Oct/2012:14:46:34size: 44
remote_ip: 192.168.0.1