python 正則表達式 練習題


會用到的語法

正則字符

釋義

舉例

+

前面元素至少出現一次

ab+:ab、abbbb 等

*

前面元素出現0次或多次

ab*:a、ab、abb 等

?

匹配前面的一次或0次

Ab?: A、Ab 等

^

作為開始標記

^a:abc、aaaaaa等

$

作為結束標記

c$:abc、cccc 等

\d

數字

3、4、9 等

\D

非數字

A、a、- 等

[a-z]

A到z之間的任意字母

a、p、m 等

[0-9]

0到9之間的任意數字

0、2、9 等

注意:

1. 轉義字符

>>> s
'(abc)def'
>>> m = re.search("(\(.*\)).*", s)
>>> print m.group(1)
(abc)

  

group()用法參考

2. 重復前邊的字串多次

import re

a = "kdla123dk345"
b = "kdla1123345"
m = re.search("([0-9]+(dk){0,1})[0-9]+", a)
print (m.group(0),m.group(1),m.group(2))
m = re.search("([0-9]+(dk){0,1})[0-9]+", b)
print (m.group(0),m.group(1),m.group(2))



123dk345 123dk dk   
1123345 112334 None     #group(1) 截獲了多次的組返回最后一次截獲的子串。

  

示例

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

代碼

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, "不全是小寫!")


s1: adkkdk 全為小寫
abc123efg 不全是小寫!

  

 

究其因

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

2. 匹配的形式為: re.search(正則表達式, 帶匹配字串)或re.match(正則表達式, 帶匹配字串)。兩者區別在於后者默認以開始符(^)開始。因此,

re.search('^[a-z]+$', s1) 等價於 re.match('[a-z]+$', s2)

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

group用於把匹配結果分組

例如

復制代碼
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)正則表達式中的三組括號把匹配結果分成三組

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

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

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

3)當然鄭則表達式中沒有括號,group(1)肯定不對了。

二.  首字母縮寫詞擴充

具體示例

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***
規律    大寫字母 + 小寫(大於等於1個)+ 空格

參考代碼

復制代碼
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')
復制代碼

結果

問題

上面代碼對於例子中的前3個是正確的,但是后面的兩個就錯了,因為大寫字母開頭的詞語之間還夾雜着小寫字母詞

規律 

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

參考代碼

復制代碼
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')
復制代碼

技巧

中間的 小寫字母集合+一個空格,看成一個整體,就加個括號。要么同時有,要么同時沒有,這樣需要用到?,匹配前方的整體。

三. 去掉數字中的逗號

具體示例

在處理自然語言時123,000,000如果以標點符號分割,就會出現問題,好好的一個數字就被逗號肢解了,因此可以先下手把數字處理干凈(逗號去掉)。

分析

數字中經常是3個數字一組,之后跟一個逗號,因此規律為:***,***,***

正則式

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

參考代碼3-1

復制代碼
import re

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

for com in p.finditer(sen): #搜索string,返回一個順序訪問每一個匹配結果(Match對象)的迭代器。 
    mm = com.group()
    print "hi:", mm
    print "sen_before:", sen
    sen = sen.replace(mm, mm.replace(",", ""))
    print "sen_back:", sen, '\n'
復制代碼

結果

技巧

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

搜索string,返回一個順序訪問每一個匹配結果(Match對象)的迭代器。      

參考代碼3-2

復制代碼
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
復制代碼

結果

延伸

這樣的程序針對具體問題,即數字3位一組,如果數字混雜與字母間,干掉數字間的逗號,即把“abc,123,4,789,mnp”轉化為“abc,1234789,mnp”

思路

更具體的是找正則式“數字,數字”找到后用去掉逗號的替換

參考代碼3-3

復制代碼
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
復制代碼

結果

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

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

復制代碼
# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中國成立"
m1 =  "比一九九零年低百分之五點二"
m2 =  '人一九九六年擊敗俄軍,取得實質獨立'

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

fuc(m0)
fuc(m1)
fuc(m2)
復制代碼

運行結果

可以看出第二個、第三個都出現了錯誤。

改進——准化成unicode識別

復制代碼
# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中國成立"
m1 =  "比一九九零年低百分之五點二"
m2 = '人一九九六年擊敗俄軍,取得實質獨立'

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)
復制代碼

結果

識別出來可以通過替換方式,把漢字替換成數字。

參考

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

有一個文件,文件名為output_1981.10.21.txt 。下面使用Python: 讀取文件名中的日期時間信息,並找出這一天是周幾。將文件改名為output_YYYY-MM-DD-W.txt (YYYY:四位的年,MM:兩位的月份,DD:兩位的日,W:一位的周幾,並假設周一為一周第一天)

import re  
import time  
import datetime  
  
filename = "output_1981.10.21.txt"  
m = re.search("output_(\d{4}.\d{2}.\d{2})", filename)  
searchResult = m.group(1)  
print ("matcht result: %s" % searchResult)  
dates = searchResult.split('.')  
for date in dates:  
    print date  
year = dates[0]  
month = dates[1]  
day = dates[2]  
xingqi = datetime.datetime(int(year), int(month), int(day)).strftime("%w")  
# replace to new filename  
theReplacePart = '%s-%s-%s-%s' % (year,month,day,xingqi)  
print 'the new filename is: %s' % theReplacePart  
newfileName = re.sub("\d{4}.\d{2}.\d{2}", theReplacePart, filename)  
print newfileName  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM