欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python中正則表達(dá)式的使用詳解

 更新時(shí)間:2014年10月17日 09:11:22   投稿:hebedich  
這篇文章主要介紹了python中正則表達(dá)式的使用詳解,另附上一些常用的Python正則例子,有需要的朋友可以參考下

從學(xué)習(xí)Python至今,發(fā)現(xiàn)很多時(shí)候是將Python作為一種工具。特別在文本處理方面,使用起來(lái)更是游刃有余。

說(shuō)到文本處理,那么正則表達(dá)式必然是一個(gè)絕好的工具,它能將一些繁雜的字符搜索或者替換以非常簡(jiǎn)潔的方式完成。

我們?cè)谔幚砦谋镜臅r(shí)候,或是查詢抓取,或是替換.

一.查找
如果你想自己實(shí)現(xiàn)這樣的功能模塊,輸入某一個(gè)ip地址,得到這個(gè)ip地址所在地區(qū)的詳細(xì)信息.

然后你發(fā)現(xiàn)http://ip138.com 可以查出很詳細(xì)的數(shù)據(jù)

但是人家沒(méi)有提供api供外部調(diào)用,但是我們可以通過(guò)代碼模擬查詢?nèi)缓髮?duì)結(jié)果進(jìn)行抓取.

通過(guò)查看這個(gè)相應(yīng)頁(yè)面的源碼,我們可以發(fā)現(xiàn),結(jié)果是放在三個(gè)<li></li>中的

復(fù)制代碼 代碼如下:

<table width="80%"  border="0" align="center" cellpadding="0" cellspacing="0"> 
    <tr> 
        <td align="center"><h3>ip138.com IP查詢(搜索IP地址的地理位置)</h3></td> 
    </tr> 
    <tr> 
        <td align="center"><h1>您查詢的IP:121.0.29.231</h1></td> 
    </tr> 
    <tr> 
 
        <td align="center"><ul class="ul1"><li>本站主數(shù)據(jù):浙江省杭州市 阿里巴巴</li><li>參考數(shù)據(jù)一:浙江省杭州市 阿里巴巴</li><li>參考數(shù)據(jù)二:浙江省杭州市 阿里巴巴</li></ul></td> 
    </tr> 
    <tr> 
        <td align="center">如果您發(fā)現(xiàn)查詢結(jié)果不詳細(xì)或不正確,請(qǐng)使用<a href="ip_add.asp?ip=121.0.29.231"><font color="#006600"><b>IP數(shù)據(jù)庫(kù)自助添加</b></font></a>功能進(jìn)行修正<br/><br/> 
        <iframe src="/jss/bd_460x60.htm" frameborder="no" width="460" height="60" border="0" marginwidth="0" marginheight="0" scrolling="no"></iframe><br/><br/></td> 
 
    </tr> 
    <form method="get" action="ips8.asp" name="ipform" onsubmit="return checkIP();"> 
    <tr> 
        <td align="center">IP地址或者域名:<input type="text" name="ip" size="16"> <input type="submit" value="查詢"><input type="hidden" name="action" value="2"></td> 
    </tr><br> 
<br> 
    </form> 
</table>   

如果你了解正則表達(dá)式你可能會(huì)寫出

正則表達(dá)式

復(fù)制代碼 代碼如下:

(?<=<li>).*?(?=</li>)

這里使用了前瞻:lookahead 后顧: lookbehind,這樣的好處就是匹配的結(jié)果中就不會(huì)包含html的li標(biāo)簽了.

如果你對(duì)自己寫的正則表達(dá)式不是很自信的話,可以在一些在線或者本地的正則測(cè)試工具進(jìn)行一些測(cè)試,以確保正確.

接下來(lái)的工作就是如果用Python實(shí)現(xiàn)這樣的功能,首先我們得將正則表達(dá)式表示出來(lái):

復(fù)制代碼 代碼如下:

r"(?<=<li>).*?(?=</li>)" 

 Python中字符串前面加上前導(dǎo)r這個(gè)字符,代表這個(gè)字符串是R aw String(原始字符串),也就是說(shuō)Python字符串本身不會(huì)對(duì)字符串中的字符進(jìn)行轉(zhuǎn)義.這是因?yàn)檎齽t表達(dá)式也有轉(zhuǎn)義字符之說(shuō),如果雙重轉(zhuǎn)義的話,易讀性很差.

這樣的串在Python中我們把它叫做"regular expression pattern"

如果我們對(duì)pattern進(jìn)行編譯的話

復(fù)制代碼 代碼如下:

prog = re.compile(r"(?<=<li>).*?(?=</li>)") 

我們便可以得到一個(gè)正則表達(dá)式對(duì)象regular expression object,通過(guò)這個(gè)對(duì)象我們可以進(jìn)行相關(guān)操作.

比如

復(fù)制代碼 代碼如下:

result=prog.match(string) 
##這個(gè)等同于 
result=re.match(r"(?<=<li>).*?(?=</li>)",string) 
##但是如果這個(gè)正則需要在程序匹配多次,那么通過(guò)正則表達(dá)式對(duì)象的方式效率會(huì)更高 

接下來(lái)就是查找了,假設(shè)我們的html結(jié)果已經(jīng)以html的格式存放在text中,那么通過(guò)

復(fù)制代碼 代碼如下:

result_list = re.findall(r"(?<=<li>).*?(?=</li>)",text) 

便可以取得所需的結(jié)果列表.

二.替換
使用正則表達(dá)式進(jìn)行替換非常的靈活.

比如之前我在閱讀Trac這個(gè)系統(tǒng)中wiki模塊的源代碼的時(shí)候,就發(fā)現(xiàn)其wiki語(yǔ)法的實(shí)現(xiàn)就是通過(guò)正則替換進(jìn)行的.

在使用替換的時(shí)候會(huì)涉及到正則表達(dá)式中的Group分組的概念.

假設(shè)wiki語(yǔ)法中使用!表示轉(zhuǎn)義字符即感嘆號(hào)后面的功能性字符會(huì)原樣輸出,粗體的語(yǔ)法為

寫道
'''這里顯示為粗體'''
 那么有正則表達(dá)式為

復(fù)制代碼 代碼如下:

r"(?P<bold>!?''')" 

  這里的?P<bold>是Python正則語(yǔ)法中的一部分,表示其后的group的名字為"bold"

  下面是替換時(shí)的情景,其中sub函數(shù)的第一個(gè)參數(shù)是pattern,第二個(gè)參數(shù)可以是字符串也可以是函數(shù),如果是字符串的話,那么就是將目標(biāo)匹配的結(jié)果替換成指定的結(jié)果,而如果是函數(shù),那么函數(shù)會(huì)接受一個(gè)match object的參數(shù),并返回替換后的字符串,第三個(gè)參數(shù)便是源字符串.

復(fù)制代碼 代碼如下:

result = re.sub(r"(?P<bold>!?''')", replace, line) 

每當(dāng)匹配到一個(gè)三單引號(hào),replace函數(shù)便運(yùn)行一次,可能這時(shí)候需要一個(gè)全局變量記錄當(dāng)前的三單引號(hào)是開(kāi)還是閉,以便添加相應(yīng)的標(biāo)記.

在實(shí)際的trac wiki的實(shí)現(xiàn)的時(shí)候,便是這樣通過(guò)一些標(biāo)記變量,來(lái)記錄某些語(yǔ)法標(biāo)記的開(kāi)閉,以決定replace函數(shù)的運(yùn)行結(jié)果.

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

示例

一. 判斷字符串是否是全部小寫

代碼

復(fù)制代碼 代碼如下:

# -*- coding: cp936 -*-
import re 
s1 = 'adkkdk'
s2 = 'abc123efg'

an = re.search('^[a-z]+$', s1)
if an:
    print 's1:', an.group(), '全為小寫'
else:
    print s1, "不全是小寫!"

an = re.match('[a-z]+$', s2)
if an:
    print 's2:', an.group(), '全為小寫'
else:
    print s2, "不全是小寫!"

結(jié)果

 

究其因

1. 正則表達(dá)式不是python的一部分,利用時(shí)需要引用re模塊

2. 匹配的形式為: re.search(正則表達(dá)式, 帶匹配字串)或re.match(正則表達(dá)式, 帶匹配字串)。兩者區(qū)別在于后者默認(rèn)以開(kāi)始符(^)開(kāi)始。因此,

re.search('^[a-z]+$', s1) 等價(jià)于 re.match('[a-z]+$', s2)
3. 如果匹配失敗,則an = re.search('^[a-z]+$', s1)返回None

group用于把匹配結(jié)果分組

例如

復(fù)制代碼 代碼如下:

import re
a = "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)   #123abc456,返回整體
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)   #123
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)   #abc
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)   #456

1)正則表達(dá)式中的三組括號(hào)把匹配結(jié)果分成三組

  group() 同group(0)就是匹配正則表達(dá)式整體結(jié)果

  group(1) 列出第一個(gè)括號(hào)匹配部分,group(2) 列出第二個(gè)括號(hào)匹配部分,group(3) 列出第三個(gè)括號(hào)匹配部分。

2)沒(méi)有匹配成功的,re.search()返回None

3)當(dāng)然鄭則表達(dá)式中沒(méi)有括號(hào),group(1)肯定不對(duì)了。

二.  首字母縮寫詞擴(kuò)充

具體示例

FEMA   Federal Emergency Management Agency
IRA    Irish Republican Army
DUP    Democratic Unionist Party

FDA    Food and Drug Administration
OLC    Office of Legal Counsel
分析

縮寫詞  FEMA
分解為  F*** E*** M*** A***
規(guī)律    大寫字母 + 小寫(大于等于1個(gè))+ 空格
參考代碼

復(fù)制代碼 代碼如下:

import re
def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr):
        ma += abbr[i] + "[a-z]+" + ' '
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
        return p.group()
    else:
        return ''

print expand_abbr("Welcome to Algriculture Bank China", 'ABC')

結(jié)果

問(wèn)題

上面代碼對(duì)于例子中的前3個(gè)是正確的,但是后面的兩個(gè)就錯(cuò)了,因?yàn)榇髮懽帜搁_(kāi)頭的詞語(yǔ)之間還夾雜著小寫字母詞

規(guī)律

大寫字母 + 小寫(大于等于1個(gè))+ 空格 + [小寫+空格](0次或1次)

參考代碼

復(fù)制代碼 代碼如下:

import re
def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr-1):
        ma += abbr[i] + "[a-z]+" + ' ' + '([a-z]+ )?'
    ma += abbr[lenabbr-1] + "[a-z]+"
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
        return p.group()
    else:
        return ''

print expand_abbr("Welcome to Algriculture Bank of China", 'ABC')

技巧

中間的 小寫字母集合+一個(gè)空格,看成一個(gè)整體,就加個(gè)括號(hào)。要么同時(shí)有,要么同時(shí)沒(méi)有,這樣需要用到?,匹配前方的整體。

三. 去掉數(shù)字中的逗號(hào)

具體示例

在處理自然語(yǔ)言時(shí)123,000,000如果以標(biāo)點(diǎn)符號(hào)分割,就會(huì)出現(xiàn)問(wèn)題,好好的一個(gè)數(shù)字就被逗號(hào)肢解了,因此可以先下手把數(shù)字處理干凈(逗號(hào)去掉)。

分析

數(shù)字中經(jīng)常是3個(gè)數(shù)字一組,之后跟一個(gè)逗號(hào),因此規(guī)律為:***,***,***

正則式

[a-z]+,[a-z]?

參考代碼3-1

復(fù)制代碼 代碼如下:

import re

sen = "abc,123,456,789,mnp"
p = re.compile("\d+,\d+?")

for com in p.finditer(sen):
    mm = com.group()
    print "hi:", mm
    print "sen_before:", sen
    sen = sen.replace(mm, mm.replace(",", ""))
    print "sen_back:", sen, '\n'

結(jié)果

技巧

使用函數(shù)finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):

搜索string,返回一個(gè)順序訪問(wèn)每一個(gè)匹配結(jié)果(Match對(duì)象)的迭代器。     

參考代碼3-2

復(fù)制代碼 代碼如下:

sen = "abc,123,456,789,mnp"
while 1:
    mm = re.search("\d,\d", sen)
    if mm:
        mm = mm.group()
        sen = sen.replace(mm, mm.replace(",", ""))
        print sen
    else:
        break

結(jié)果

延伸

這樣的程序針對(duì)具體問(wèn)題,即數(shù)字3位一組,如果數(shù)字混雜與字母間,干掉數(shù)字間的逗號(hào),即把“abc,123,4,789,mnp”轉(zhuǎn)化為“abc,1234789,mnp”

思路

更具體的是找正則式“數(shù)字,數(shù)字”找到后用去掉逗號(hào)的替換

參考代碼3-3

復(fù)制代碼 代碼如下:

sen = "abc,123,4,789,mnp"
while 1:
    mm = re.search("\d,\d", sen)
    if mm:
        mm = mm.group()
        sen = sen.replace(mm, mm.replace(",", ""))
        print sen
    else:
        break
print sen

結(jié)果

四. 中文處理之年份轉(zhuǎn)換(例如:一九四九年--->1949年)

中文處理涉及到編碼問(wèn)題。例如下邊的程序識(shí)別年份(****年)時(shí)

復(fù)制代碼 代碼如下:

# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中國(guó)成立"
m1 =  "比一九九零年低百分之五點(diǎn)二"
m2 =  '人一九九六年擊敗俄軍,取得實(shí)質(zhì)獨(dú)立'

def fuc(m):
    a = re.findall("[零|一|二|三|四|五|六|七|八|九]+年", m)
    if a:
        for key in a:
            print key
    else:
        print "NULL"

fuc(m0)
fuc(m1)
fuc(m2)

運(yùn)行結(jié)果

可以看出第二個(gè)、第三個(gè)都出現(xiàn)了錯(cuò)誤。

改進(jìn)——準(zhǔn)化成unicode識(shí)別

復(fù)制代碼 代碼如下:

# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中國(guó)成立"
m1 =  "比一九九零年低百分之五點(diǎn)二"
m2 = '人一九九六年擊敗俄軍,取得實(shí)質(zhì)獨(dú)立'

def fuc(m):
    m = m.decode('cp936')
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", m)

    if a:
        for key in a:
            print key
    else:
        print "NULL"

fuc(m0)
fuc(m1)
fuc(m2)

結(jié)果

識(shí)別出來(lái)可以通過(guò)替換方式,把漢字替換成數(shù)字。

參考

復(fù)制代碼 代碼如下:

numHash = {}
numHash['零'.decode('utf-8')] = '0'
numHash['一'.decode('utf-8')] = '1'
numHash['二'.decode('utf-8')] = '2'
numHash['三'.decode('utf-8')] = '3'
numHash['四'.decode('utf-8')] = '4'
numHash['五'.decode('utf-8')] = '5'
numHash['六'.decode('utf-8')] = '6'
numHash['七'.decode('utf-8')] = '7'
numHash['八'.decode('utf-8')] = '8'
numHash['九'.decode('utf-8')] = '9'

def change2num(words):
    print "words:",words
    newword = ''
    for key in words:
        print key
        if key in numHash:
            newword += numHash[key]
        else:
            newword += key
    return newword

def Chi2Num(line):
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", line)
    if a:
        print "------"
        print line
        for words in a:
            newwords = change2num(words)
            print words
            print newwords
            line = line.replace(words, newwords)
    return line

相關(guān)文章

最新評(píng)論