1. 程式人生 > >Python核心程式設計第15章正則表示式練習答案

Python核心程式設計第15章正則表示式練習答案


#15-1 識別下列字串:“bat,” “bit,” “but,” “hat,” “hit,” 或 “hut”
pattern =  r'[bh][aiu]t,?'


#15-2  匹配用一個空格分隔的任意一對單詞,比如,名和姓
pattern = r'\b\w+ \w+\b'


#15-3  匹配用一個逗號和一個空格分開的一個單詞和一個字母。例如,英文人名中的姓和名的首字母
pattern = r'\b\w+, \w'


#15-4  匹配所有合法的 Python 識別符號
pattern = r'\b[a-zA-Z_](\w|_)*\b'


#15-5 匹配地址
 
#15-6  匹配簡單的以“www.”開頭,以“.com”作結尾的 Web 域名,例如:www.yahoo.com. 
#附加題:使你寫的正則表示式還支援其他頂級域名:.edu, .net 等,比如:www.ucsc.edu
pattern = r'\bwww\..*\.(com|net|edu)'


#15-7 15-8 匹配全體Python長整數的字串表示形式的集合
patternIntStr = r'''
^#從字串開始位置匹配
(\+|-)?#可選的正負號
(
(0|[1-9]\d*)#十進位制整數,0或非0
|
(0[0-7]*)#八進位制整數
|
(0[xX][0-9a-fA-F]+)#十六進位制整數
)
$#匹配到字串的結束位置
'''


#15-9 匹配全體Python浮點數的字串表示形式的集合
patternFloatStr = r'''
^#從字串開始位置匹配
(\+|-)?#可選的正負號
(
\d+\.\d*#匹配 1. 1.0 等形式,即小數部分可省略
|
\d*\.\d+#匹配 .1 0.1 等形式,即整數部分可省略
)
((e|E)(\+|-)?\d+)?#可選的科學計數法
$#匹配到字串的結束位置
'''


#15-10 匹配全體Python複數的字串表示形式的集合
patternComplexStr = r'''
^#從字串開始位置匹配
(
(\+|-)?#可選的正負號
(
\d+\.?\d*#匹配 1. 1.0 1等形式,即小數部分和小數點可省略
|
\d*\.?\d+#匹配 .1 0.1 1 等形式,即整數部分和小數點可省略
)
((e|E)(\+|-)?\d+)?#可選的科學計數法
)
{1,2}#匹配實數和虛數
(j|J)#虛數標識
$#匹配到字串的結束位置
'''


#15-11 匹配所有合法的電子郵件地址
patternEmailStr = r'''
^
[a-zA-Z]#以字母開頭
(\w|_|\.)*#使用者名稱只允許有字母、數字、下劃線、點(.)
@
(\w|\.)+#域名包括字母、數字、點(.)
$
'''


#15-12 匹配所有合法的web網站地址
patternURL = r'''
^
\.+
$
'''


#15-13 提取型別名字
patternType = r'''
'
(\w+)
'
'''


#15-14 匹配月份:1 2 3 4 01 02 10 11 12等
patternMonth = r'''
^
(0?[1-9]|1[0-2])
$
'''


#15-15 匹配信用卡卡號
creditPattern = r'''
^
\d{4}
-
(\d{6}-\d{0,5}
|
\d{4}-\d{4}-\d{0,4})
$
'''


#15-17 統計星期中的每一天出現的次數
def analyseWeekdayCount(fileObj):
weekdayPattern = re.compile(r'\b(Sun|Mon|Tue|Wed|Thu|Fri|Sat)\b')
weekdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
weekdayCnt = dict()
for weekday in weekdays:
weekdayCnt[weekday] = 0
while True:
line = fileObj.readline()
if line:
match = weekdayPattern.search(line)
print match.group()
weekdayCnt[match.group()] += 1
else:
break
print '\n'.join(['%s: %d' %(k, v) for k, v in weekdayCnt.items()])

#統計各月份出現的次數
def analyseMonthCount(fileObj):
monthPattern = re.compile(r'\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b')
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 
'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
monthCnt = dict()
for month in months:
monthCnt[month] = 0
while True:
line = fileObj.readline()
if line:
match = monthPattern.search(line)
print match.group()
monthCnt[match.group()] += 1
else:
break
print '\n'.join(['%s: %d' %(k, v) for k, v in monthCnt.items()])

#15-19 提取每行中完整的時間戳欄位
def extractTimestamp(fileObj):
timestampPattern = re.compile(r'\w{3} \w{3} \d\d \d\d:\d\d:\d\d \d{4}')
while True:
line = fileObj.readline()
if line:
match = timestampPattern.match(line)
print match.group()
else:
break


#15-20 提取每行中完整的電子郵件地址
def extractEMailAddr(fileObj):
EMailAddrPattern = re.compile(r'::([a-z]
[email protected]
[a-z]+\.[a-z]+)::')
while True:
line = fileObj.readline()
if line:
match = EMailAddrPattern.search(line)
print match.group(1)
else:
break


#15-21 提取時間戳中的月份
def extractMonth(fileObj):
monthPattern = re.compile(r'\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b')
while True:
line = fileObj.readline()
if line:
match = monthPattern.search(line)
print match.group(1)
else:
break


#15-22 提取時間戳中的年份
def extractYear(fileObj):
yearPattern = re.compile(r'\b(\d{4})::')
while True:
line = fileObj.readline()
if line:
match = yearPattern.search(line)
print match.group(1)
else:
break


#15-23 提取時間戳中的時間
def extractTime(fileObj):
timePattern = re.compile(r'\b(\d\d:\d\d:\d\d)\b')
while True:
line = fileObj.readline()
if line:
match = timePattern.search(line)
print match.group(1)
else:
break


#15-24  只從電子郵件地址中提取出登入名和域名(包括主域名和頂級域名,二者連在一起)
def joinLoginNameAndDomainName(fileObj):
EMailAddrPattern = re.compile(r'::([a-z]+)@([a-z]+\.[a-z]+)::')
while True:
line = fileObj.readline()
if line:
match = EMailAddrPattern.search(line)
print ''.join([match.group(1), match.group(2)])
else:
break

#15-25  只從電子郵件地址中提取出登入名和域名(包括主域名和頂級域名,二者分別提取)
def splitLoginNameAndDomainName(fileObj):
EMailAddrPattern = re.compile(r'::([a-z]+)@([a-z]+\.[a-z]+)::')
while True:
line = fileObj.readline()
if line:
match = EMailAddrPattern.search(line)
print ' '.join([match.group(1), match.group(2)])
else:
break

#15–26 將每行中的電子郵件地址替換為你自己的電子郵件地址
def replaceEMailAddr(fileObj):
myAddr = r'
[email protected]
'
EMailAddrPattern = re.compile(r'[a-z][email protected][a-z]+\.[a-z]+')
while True:
line = fileObj.readline()
if line:
match = EMailAddrPattern.sub(myAddr, line)
print match,
else:
break


#15–27 提取出時間戳中的月、日、年,並按照格式“月 日,年”顯示出來,且每行僅遍歷一次
def extractDate(fileObj):
#datePattern = re.compile(r'\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d\d) .{8} (\d{4})::')
datePattern = re.compile(r'\b([A-Z][a-z]{2} \d\d) .{8} (\d{4})::')
while True:
line = fileObj.readline()
if line:
match = datePattern.search(line)
print '%s, %s' %(match.group(1), match.group(2))
else:
break

#15–28 15-29 電話號碼允許包含可選的區號字首 : \d{3}-\d{3}-\d{4}
#區號中可以包含圓括號或是連字元,而且它們是可選的,就是說你寫的正則表示式可以
#匹配 800-555-1212, 或 555-1212, 或(800) 555-1212
phonePatternStr = r'''
^
(\d{3}-#區號中包括連字元
|
\(\d{3}\)\ )#區號中包括圓括號
?#區號是可選的
\d{3}-\d{4}
$
'''