python核心编程2 第十五章 练习

15-1.识别下列字符串 :“bat ”、“bit ”、“but ”、“hat ”、“hit” 或 “hut ”

1 import re
2 from random import choice
3 
4 
5 strtuple = ('bat', 'bit', 'but', 'hat', 'hit', 'hut')
6 patt = '[bh][aiu]t'
7 m = re.search(patt, choice(strtuple))
8 print(m.group())

15-2.匹配用一个空格分隔的任意一对单词 ,比如名和姓

1 import re
2 from random import choice
3 
4 
5 strtuple = ('Bei Liu', 'Yu Guan', 'Fei Zhang')
6 patt = '[A-Za-z]+\s[A-Za-z]+'
7 m = re.search(patt, choice(strtuple))
8 print(m.group())

15-3.匹配用一个逗号和一个空格分开的一个单词和一个字母 。例如英文人名中的姓和名的首字母

1 import re
2 from random import choice
3 
4 
5 strtuple = ('Bei, L', 'Yu, G', 'Fei, Z')
6 patt = '[A-Za-z]+,\s[A-Za-z]?'
7 m = re.search(patt, choice(strtuple))
8 print(m.group())

15-4.匹配所有合法的 Python 标识符

 1 import re
 2 from random import choice
 3 
 4 
 5 strtuple = ('Abc_123', '123abc', '_abc123_', 'abcDef')
 6 patt = '[A-Za-z_](\w+|_)*'
 7 elem = choice(strtuple)
 8 m = re.match(patt, elem)
 9 if m is not None:
10     print(m.group())
11 else:
12     print('Mismatch:', elem)

15-5.请根据你 (读者〉 本地关于地址的格式写法匹配一个街道地址 (写出的正则表达式要尽可能通
用以匹配任意数目 的表示街道名字的单词 ,包括类型指示〉 。比如,美国的街道地址使用这样 的格式:1180 Bordeaux Drive 。

使你写的正则表达式尽可能通用,要求能够匹配多个单词的街道名字 ,如:3120 De la Cruz Boulevard 。

1 import re
2 from random import choice
3 
4 strtuple = ('1180 Bordeaux Drive', '3120 De la Cruz Boulevard')
5 patt = '\d{4}\s\w+\s\w+(\s\w+\s\w+)?'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

15-6.匹配简单的以 “WWW. ” 开头 ,以 “.com” 作结尾的 Web 域名 ,例如 :www.yahoo.com.
附加题:使你写的正则表达式还支持其他顶级域名如 .edu 、.net 等比如 www.ucsc.edu 。

1 import re
2 from random import choice
3 
4 strtuple = ('http://www.cnki.net', 'http://www.neea.edu.cn', 'http://www.pbccrc.org.cn',
5             'https://gab.122.gov.cn', 'www.cnblogs.com')
6 patt = '(http(s)?://)?\w{3}\.\w+\.\w{3}(\.cn)?'
7 m = re.match(patt, choice(strtuple)).group()
8 print(m)

15-7.匹配全体Python整型的字符串表示形式的集合

1 import re
2 from random import choice
3 
4 strtuple = ('123', '456', '789')
5 patt = '\d+'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

15-8.匹配全体Python长整型的字符串表示形式的集合

1 import re
2 from random import choice
3 
4 strtuple = ('11111L', '222222222222222222L', '33L')
5 patt = '\d+L'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

 15-9.匹配全体Python浮点型的字符串表示形式的集合

1 import re
2 from random import choice
3 
4 strtuple = ('1.01', '2.0', '3.141592654')
5 patt = '\d+\.\d+'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

15-10.匹配全体Python复数的字符串表示形式的集合

1 import re
2 from random import choice
3 
4 strtuple = ('1+2.3j', '2.1+5j', '5.3+0.5j')
5 patt = '((\d+)?(\d+\.\d+)?\+(\d+)?(\d+\.\d+)?)j'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

15-11.匹配所有合法的电子邮件地址 (先写出一个限制比较宽松的正则表达式 ,然后尽可能加强限制条件 ,但要保证功能的正确性) 。

1 import re
2 from random import choice
3 
4 strtuple = ('abc@163.com','123@sina.com','456@sina.cn', 'abc@abc.abc.com')
5 patt = '\w+@\w+(\.\w+)?\.\w{1,3}'
6 m = re.match(patt, choice(strtuple)).group()
7 print(m)

 15-12.匹配所有合法的 Web  网站地址 (URL)(先写出一个限制比较宽松的正则表达式 ,然后尽可能加强限制条件 ,但要保证功能的正确性) 。

1 import re
2 from random import choice
3 
4 strtuple = ('http://www.cnki.net', 'http://www.neea.edu.cn', 'http://www.pbccrc.org.cn',
5             'https://gab.122.gov.cn', 'www.cnblogs.com')
6 patt = '(http(s)?://)?\w{3}\.\w+\.\w{3}(\.cn)?'
7 m = re.match(patt, choice(strtuple)).group()
8 print(m)

 15-13.type(). type()内建函数返回一个对象类型 ,此对象显示为 Python的字符串形式 ,如下所示 :
>>> type ( 0)
<type ’ int ’>
>>> type ( .34 )
<type ’ f loat ’>
>>> type (dir)
<type  ’ builtin_f unction_or_method ’>
请写一个正则表达式,能从这个字符串中提取出类型的名字。你的函数能实现以下功能:如果 字符串 “<type ‘int’>“ 做输入,会返回类型 “int” (返回其他类型也同理 ,如,返回类型 ‘float’ , ‘builtin_function_or_method’ 等)。提示:正确的结果保存在类和某些内建类型__name__属性里

1 import re
2 from random import choice
3 
4 strtuple = (0, 0.34, dir)
5 typestr = type(choice(strtuple))
6 patt = "<\w+ '(\w+)'>"
7 m = re.match(patt, str(typestr))
8 print(m.group(1))

 15-14.正则表达式 。在 15.2 小节里 ,我们给出一个匹配由一位或两位数字代表一月到九月的字符串
形式 (“ 0?[1-9]”)。请写出一个正则表达式表示标准日历上其他的三个月(十月、十一月、十二月)。

1 import re
2 from random import choice
3 
4 btuple = (10, 11, 12)
5 patt = '1+[0-2]'
6 m = re.match(patt, str(choice(btuple)))
7 print(m.group())

15-15.正则表达式 。在 15.2 小节里,我们给出一个匹配信用卡卡号的模式:(“[0-9]{15, 16}”)。但这个模式不允许用连字符号分割信用卡卡号中的数字 。请写出一个允许使用连字符的正则表达式,但要求连字符必须出现在正确的位置 。例如,15位的信用卡卡号的格式是 4-6-5 ,表示四个数字,一个连字符 ,后面接 6 个数字、1 个连字符 ,最后是 5 个数字 。16 位的信用卡卡号的格式是 4-4-4-4 ,数位不足时 ,添 0 补位。附加题:有一个用于确定某个信用卡卡号是否 合法的算法 。请写一段代码 ,它不但能识别格式正确的信用卡卡号 ,还能验证它的有效性 。

1 import re
2 from random import choice
3 
4 strtuple = ('1234-123456-12345', '1234-4321-1234-4321')
5 patt = '\d{4}-\d{6}-\d{5}|\d{4}-\d{4}-\d{4}-\d{4}'
6 m = re.match(patt, choice(strtuple))
7 print(m.group())

15-16.修改脚本gendata.py的代码,使数据直接写入文件redata.txt中,而不是输出到屏幕上。

 1 from random import randint, choice
 2 from string import ascii_lowercase
 3 from sys import maxsize
 4 from time import ctime
 5 
 6 domes = ('com', 'edu', 'net', 'org', 'gov')
 7 
 8 for i in range(randint(5, 10)):
 9     dtint = randint(0, maxsize-1)
10     dtstr = ctime(dtint)
11 
12     shorter = randint(4, 7)
13     em = ''
14     for j in range(shorter):
15         em += choice(ascii_lowercase)
16 
17     longer = randint(shorter, 12)
18     dn = ''
19     for j in range(longer):
20         dn += choice(ascii_lowercase)
21 
22     data = '%s::%s@%s.%s::%d-%d-%d' % (dtstr, em, dn, choice(domes), dtint, shorter, longer)
23     with open('redata.txt', 'a') as f:
24         f.write(data + '\n')

15-17.统计生成的 redata.txt 文件中 ,星期中的每一天出现的次数 (或统计各月份出现的次数〉

 1 import re
 2 
 3 days = {'Mon': 0, 'Tue': 0, 'Wed': 0, 'Thu': 0, 'Fri': 0, 'Sat': 0, 'Sun': 0}
 4 
 5 months = {'Jan': 0, 'Feb': 0, 'Mar': 0, 'Apr': 0, 'May': 0, 'Jun': 0, 'Jul': 0,
 6           'Aug': 0, 'Sep': 0, 'Oct': 0, 'Nov': 0, 'Dec': 0}
 7 
 8 patt = '(\w{3})\s(\w{3})'
 9 
10 f = open('redata.txt')
11 for line in f:
12     m = re.match(patt, line.strip())
13     if m.group(1) in days:
14         days[m.group(1)] += 1
15     if m.group(2) in months:
16         months[m.group(2)] += 1
17 f.close()
18 
19 for key in days:
20     print('%s-%d' % (key, days[key]), end='  ')
21 print()
22 for key in months:
23     print('%s-%d' % (key, months[key]), end='  ')

 15-18.通过检查每个输出行中整型字段部分的第一个整型是否和该行开头的时间戳相匹配来验证redata.txt  中的数据是否完好。

 1 import re
 2 
 3 patt = '\d+\s\d+:\d+:\d+'
 4 
 5 f = open('redata.txt')
 6 for line in f:
 7     lines = line.strip()
 8     m = re.search(patt, lines)
 9     if m is not None:
10         print('Data is intact')
11     else:
12         print(lines)
13 f.close()

15-19.提取出每行中完整的时间戳字段

1 import re
2 
3 patt = '\d+:\d+:\d+\s\d+'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group())

15-20.提取出每行中完整的电子邮件地址

1 import re
2 
3 patt = '\w+@\w+\.\w{3}'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group())

15-21.只提取出时间戳字段中的月份。

1 import re
2 
3 patt = '\w{3}\s(\w{3})'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.match(patt, line.strip())
8     print(m.group(1))

15-22.只提取出时间戳字段中的年份 。

1 import re
2 
3 patt = '\d+:\d+:\d+\s(\d+)'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group(1))

15-23.只提取出时间戳字段中的值 (格式:HH:MM:SS )。

1 import re
2 
3 patt = '\d+:\d+:\d+'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group())

15-24.只从电子邮件地址中提取出登录名和域名   (包括主域名和顶级域名 ,二者连在一起〉

1 import re
2 
3 patt = '(\w+)@(\w+\.\w{3})'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print('login:',m.group(1), '\ndomain:', m.group(2))

15-25.只从电子邮件地址中提取出登录名和域名   (包括主域名和顶级域名 ,二者分别提取〉

1 import re
2 
3 patt = '(\w+)@(\w+)\.(\w{3})'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print('login:',m.group(1), '\nprimary domain:', m.group(2),
9           '\ntop level domain:', m.group(3))

15-26.将每行中的电子邮件地址替换为你自己的电子邮件地址 。

 1 import re
 2 
 3 patt = '\w+@\w+\.\w{3}'
 4 mail = 'abc@abc.com'
 5 
 6 f = open('redata.txt')
 7 for line in f:
 8     m = re.sub(patt, mail, line.strip())
 9     with open('newredata.txt', 'a') as newfile:
10         newfile.write(m + '\n')
11 f.close()

15-27.提取出时间戳中的月 、日、年,并按照格式 “月、日、年” 显示出来 ,且每行仅遍历一次 。 

1 import re
2 
3 patt = '(\w{3})\s\s?(\d+)\s\d+:\d+:\d+\s(\d+)'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group(1), m.group(2), m.group(3))

15-28.区号(第一组的三个数字和它后面的连字符〉是可选的 ,即,你写的正则表达式对 800-555-1212

和 555-1212 都可以匹配 。

1 import re
2 
3 patt = '(\d+-)?\d+-\d+'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group())

15-29.区号中可以包含圆括号或是连字符 ,而且它们是可选的 ,就是说你写的正则表达式可以匹配
800-555-1212 、555-1212 或 ( 800) 555-12120

1 import re
2 
3 patt = '(\(\d+\))?(\d+-)?\d+-\d+'
4 
5 f = open('redata.txt')
6 for line in f:
7     m = re.search(patt, line.strip())
8     print(m.group())
点赞