正则表达式的核心在于规则。
在编写规则时,正则表达式提供了很多元字符,需要分析业务规则去考虑需要用到的元字符(太多了,不要去背啦)。
参考菜鸟教程:https://www.runoob.com/regexp/regexp-metachar.html
第1题
1- 1 识别后续的字符串:“ bat”、“ bit”、“ but”、“ hat”、“ hit” 或者“ hut”。
分析:以b或h开头,中间为a或i或u,以t结尾,长度为3.
随机生成100个单词,匹配输出符合规则的单词。
import re, random
def word_list(letter_list, length, num):
'''
生成指定字母生成的单词集。从letter_list中取length次生成一个单词。
:param letter_list: 指定的字母集
:param length: 单词长度
:param num: 单词数量
:return: 单词集
'''
words = []
while num > 0:
num -= 1
word = random.sample(letter_list, length)
words.append(''.join(word))
return words
a = word_list(['h', 'u', 'i', 'a', 'm', 'b', 't'], 3, 100)
r = re.findall('[bh][aiu]t', ','.join(a))
print(r)
>['hit', 'bat', 'hat', 'hat']
第2题
1- 2 匹配由单个空格分隔的任意单词对, 也就是姓和名。
分析:姓和名都应该以大写字母开头,且名字中只能包含字母。
import re, random
def name_list(surname_list, given_name_list, num):
'''
每次从surname和given_name中随机选取一个字符串,生成一组姓名组合,以空格分隔姓和名
random.choice(列表)可以实现随机选取
:param surname_list: 姓的列表
:param given_name_list: 名的列表
:param num: name_list的长度
:return: 姓名列表
'''
names = []
while num > 0:
num -= 1
name = random.choice(surname_list) + ' ' + random.choice(given_name_list)
names.append(name)
return names
a = name_list(['Hark', 'Ivens', 'Johnson', '889Jak'], ['Ross', 'Julie', 'Gloria', 'Carol'], 5)
print(a)
for i in a:
patt = re.findall(r'^[A-Z][a-z]+\s[A-Z][a-z]+$', i)
if len(patt) != 0:
print(patt)
>结果:
['889Jak Gloria', 'Hark Gloria', 'Ivens Gloria', '889Jak Carol', 'Johnson Julie']
['Hark Gloria']
['Ivens Gloria']
['Johnson Julie']
第3题
1- 3 匹配由单个逗号和单个空白符分隔的任何单词和单个字母,如姓氏的
首字母。
分析:如:“Tom, a, Yaml, dance, B, 11, c”.根据我对题目的理解,应该输出Tom, a 和 dance, B。
import re
a = 'Tom, a, 11, r, dance, B, sing, cc'
r = re.findall('[a-z]{2,},\s[a-z]', a, re.I)
print(r)
结果:事实上这个结果并不满足我理解的题意,但是目前搞不定
['Tom, a', 'dance, B', 'sing, c']
第4题
1- 4 匹配所有有效 Python 标识符的集合。
分析:标识符不能与关键字同名,由下划线、字母、数字组成,必须以下划线或字母开头。
如:__init、a_b、test1等为有效标识符
11_a为无效标识符
知识点说明:\w在不加re.A时可以匹配出中文,是因为python3支持的是Unicode字符集。加re.A可以仅支持中文。
import re
import keyword
a = ['11_a', 'in', 'as', 'import','__flag__', '__fl#ag__', 'd', '123', '1_b', '__a字母a', '_1_a', '_1_a_#']
# 判断字符串是否与关键字同名
b = [flag for flag in a if flag not in keyword.kwlist]
r = [re.findall('^[a-z_]\w*$', flag, re.I | re.A) for flag in b]
print(r)
g = filter(lambda x: len(x) != 0, r)
print(list(g))
结果:
[[], ['__flag__'], [], ['d'], [], [], [], ['_1_a'], []]
[['__flag__'], ['d'], ['_1_a']]
第5题
1- 5 根据读者当地的格式,匹配街道地址(使你的正则表达式足够通用,来匹配任意数量的街道单词,包括类型名称)。例如,美国街道地址使用如下格式:1180 Bordeaux Drive。使你的正则表达式足够灵活,以支持多单词的街道名称,如3120 De la Cruz Boulevard。
分析:匹配每个地址是否是街道地址,街道地址以4位数字开头,多个单词组成,每组单词之间由空格隔开。