正则表达式
今日内容
- 正则表达式
- 正则表达式之字符组
- 正则表达式之特殊符号
- 正则表达式之量词
- 贪婪匹配和非贪婪匹配
- 作业
正则表达式
正则表达式不属于任何一个编程语言 是一个独立的学科
主要用于数据的筛选和查找
1.前戏
现在需要编写一个代码用来判断用户输入是否是中国手机号码
phone_id = input('请输入电话号码>>>>:').strip() if phone_id.isdigit(): if len(phone_id) == 11: if phone_id.startswith('13') or phone_id.startswith('15') or phone_id.startswith( '16') or phone_id.startswith('17') or phone_id.startswith('19'): print('合格的号码') else: print('开头不合法') else: print('电话号码必须是11位') else: print('电话号码必须是纯数字') # 这样也可以判断处电话号码是否合格 但是这样写太多了 可以使用正则表达式简便写 import re phone_id = input('请输入电话号码>>>>:').strip() if re.match('0?^(13|15|16|17|19)[0-9]{9}',phone_id): print(f'电话号码合格{phone_id}') else: print('电话号码不合格') # 这样就也可以判断电话号码是否合格 还可以省代码简便快捷 ''' 总结: 正则表达式就是通过一些特殊符号的组合产生一些特殊含义 然后在字符串中筛选出符合条件的数据 '''
正则表达式之字符组
正则表达式线上测试网站: http://tool.chinaz.com/regex/
[0-9] 匹配数字0-9中的任意一个数字(包括0和9) # 就是能够把一串字符串中的所有数字都提取出来一次只会针对一个数据 [A-Z] 匹配大写字母A-Z中的任意一个字母(包括A和Z) # 就是能够用把一串字符串中的所有大写字母都提取出来一次只会针对一个数据 [a-z] 匹配小写字母a-z中的任意一个字母(包括a和z) # 就是能够把一串字符串中所有的小写字母都提取出来一次只会针对一个数据
如果括号中多个数据值那么他们批次是或的关系 [0-9a-zA-Z] 就是数字、小写字母、大写字母都可以 ''' 字符组在没有量词修饰的情况下一次只会针对一个数据值 '''
正则表达式之特殊符号
''' . 匹配除换行符之外的任意一个字符 \w 匹配字母或数字或下划线 \W 匹配除字母或数字或下划线之外的任意一个字符 \d 匹配数字 ^ 匹配字符串的开头 $ 匹配字符串的结尾 ps: ^和 $组合使用可以明确的限制想要查找的具体数据 ^数据$ a|b 匹配a字符或b字符 ps: |管道符在很多场景中都是表示或 () 给正则表达式分组 不影响正则表达式的匹配 ps: 用于给正则表达式起别名 分组获取对应的数据 [] 匹配字符组中的字符 [^] 匹配除了字符组中字符的所有字符 ''' # 在没有量词修饰的情况下一个字符一次只会针对一个数据值
正则表达式之量词
''' * 重复零次或更多次(默认更多次) + 重复一次或更多次(默认更多次) ? 重复零次或一次(默认更多次) {n} 重复n次 {n,} 重复n次或更多次 {n,m} 重复n到m次 在正则表达式中所有的量词默认匹配的都是贪婪匹配(就是尽可能多的取值) ''' # 量词不能单独使用 必须跟在表达式后面 并且只能影响紧挨的着的左边的那一个
正则表达式之练习题
''' 正则 待匹配的字符 匹配结果 海. 海燕海娇海东 海燕 海娇 海东 三条结果 匹配所有"海." 的字符 ^海. 海燕海娇海东 海燕 一条结果 只从开头匹配是"海."的字符 海.$ 海燕海娇海东 海东 一条结果 只从结尾匹配是"海."的字符 李.? 李杰和李莲英和李二棍子 李杰 李莲 李二 三条结果 ?表示重复零次或一次, 所以只匹配"李"后面任意一个字符 李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子 一条结果 *表示重复零次或多次, 所以匹配"李"后面0个或多个字符 李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子 一条结果 +表示重复一次或多次, 所以匹配"李"后面一个或多个字符 李.{1,2} 李杰和李莲英和李二棍子 李杰和 李莲英 李二棍 三条结果 {1, 2}表示匹配1到2次任意字符, 所以匹配"李"后面一个或两个字符 李[杰莲英二棍子]* 李杰和李莲英和李二棍子 李杰 李莲英 李二棍子 三条结果 [杰莲英二棍子]*表示匹配字符组中任意一个字符 eg:(李杰 李杰莲 李杰莲英...) 李[^和]* 李杰和李莲英和李二棍子 李杰 李莲英 李二棍子 三条结果 [^和]* 表示匹配除了字符组中的和以外的任意字符 [\d] 456bdha3 4 5 6 3 四条结果 [\d]表示匹配任意一个数字 [\d]+ 456bdha3 456 3 两条结果 [\d]*表示匹配任意数字 经过量词的修饰就可以改变提取的结果 '''
贪婪匹配和非贪婪匹配
1.贪婪匹配
''' 贪婪匹配: 1. 待匹配的文本:<script>alert(123)</script> 正则表达式 <.*> 匹配结果: <script>alert(123)</script> 2. 待匹配的文本:<script>alert(123)</script>abs 正则表达式 <.*> 匹配结果: <script>alert(123)</script> 就是<匹配<
然后.*就是除了换行符什么都可以匹配遇到倒数第一个>停下匹配
然后>匹配最后一个> '''
2.非贪婪匹配
''' 非贪婪匹配: 1. 待匹配的文本:<script>alert(123)</script> 正则表达式 <.*?> 匹配结果: <script> </script> 2. 待匹配的文本:<script>alert(123)</script>abs 正则表达式 <.*?> 匹配结果: <script> </script> 就是<匹配<
然后.*匹配除了换行符之外的所有字符遇到第一个>就会停下匹配
>匹配遇到的第一个>
然后继续下去知道没有为止 '''
3.主意事项
''' 所有的量词默认都是贪婪匹配 但是如果后面紧跟上?就会变成非贪婪匹配 小技巧: 以后我们使用贪婪匹配和非贪婪匹配的时候一般我们都使用.*或者.*? 并且结束的标识就是上述符号两边添加的表达式决定 '''
取消转义
在正则表达式中取消斜杠与字母产生的特殊含义 就是在斜杠前面加上斜杠 \n>>>> \\n \\n>>>>\\\n 而在python中只需要在前面加上r r'\n' r'\\n'
正则表达式实战
编写校验用户手机号的正则 0?(13|14|15|17|18|19)[0-9]{9} 编写校验用户身份证的正则 \d{17}[\d|x]|\d{15} 编写校验用户邮箱的正则 \w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14} 编写校验用户qq号的正则 [1-9]([0-9]{5,11}) ''' 这些肯定在任何地方都需要这些需求, 所以已经有大佬写好了 用的时候我们只需问度娘 或则点击这个链接即可:http://tool.chinaz.com/regex/ 我们只需要知道这个怎么用 怎么修改即可 '''
作业
对购物车功能添加一些新功能
# 项目说明 # 用户数据采用json格式存储到文件目录db下 一个用户一个单独的文件 # 数据格式 {"name":"jason","pwd":123} # # ps:文件名可以直接用用户名便于校验 # 用户注册时给每个用户添加两个默认的键值对(账户余额 购物车) # {"balance":15000,"shop_car":{}} # 添加购物车功能 商品列表可以自定义或者采用下列格式 # good_list = [ # ['挂壁面',3] # ['印度飞饼', 22] # ['极品木瓜', 666], # ['土耳其土豆', 999], # ['伊拉克拌面', 1000], # ['董卓戏张飞公仔', 2000], # ['仿真玩偶', 10000] # ] # 用户可以反复添加商品,在购物车中记录数量 # {'极品木瓜':[个数,单价]} # 结算购物车 # 获取用户购物车中所有的商品计算总价并结算即可 # 针对添加购物车和结算只有登录的用户才可以执行 import os import json is_login = { 'username': None } base_dir = os.path.dirname(__file__) db_dir = os.path.join(base_dir, 'db') if not os.path.exists(db_dir): os.mkdir(db_dir) def login_auth(func): def wrapper(*args, **kwargs): if is_login.get('username'): res = func(*args, **kwargs) return res else: print('您为登入, 请先登入') login() return wrapper def register(): while True: username = input('username>>>:').strip() password = input('password>>>:').strip() file_path = os.path.join(db_dir, f'{username}.json') if os.path.exists(file_path): print('用户名已存在') break user_dict = {'username': username, 'password': password, 'balance': 15000, 'shop_car': {}} with open(file_path, 'w', encoding='utf8') as f: json.dump(user_dict, f, ensure_ascii=False) print(f'{username}注册成功') break def login(): username = input('username>>>').strip() password = input('password>>>:').strip() file_path = os.path.join(db_dir, f'{username}.json') if os.path.exists(file_path): with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) if password == user_dict.get('password'): print('登入成功') is_login['username'] = username return else: print('密码错误') else: print('用户名不存在') def user_switch(): is_login['username'] = None login() @login_auth def add_shop_car(): file_path = os.path.join(db_dir, f"{is_login.get('username')}.json") good_list = [ ['挂壁面', 3], ['印度飞饼', 22], ['极品木瓜', 666], ['土耳其土豆', 999], ['伊拉克拌面', 1000], ['董卓戏张飞公仔', 2000], ['仿真玩偶', 10000] ] temp_shop_car = {} while True: for i, j in enumerate(good_list): print(f'商品编号:{i} | 商品名称:{j[0]} | 商品单价:{j[1]}') choice = input('请输入商品编号或则输入(q)退出>>>:').strip() if choice == 'q': with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) real_shop_car = user_dict.get('shop_car') for good_name in temp_shop_car: if good_name not in real_shop_car: real_shop_car[good_name] = temp_shop_car[good_name] else: real_shop_car[good_name][0] += temp_shop_car[good_name][0] user_dict['shop_car'] = real_shop_car with open(file_path, 'w', encoding='utf8') as f: json.dump(user_dict, f, ensure_ascii=False) print('购物车添加成功') break if not choice.isdigit(): print('商品编号必须是纯数字') continue choice = int(choice) if choice not in range(len(good_list)): print('没有该商品') return target_num = input('请输入商品数量>>>:').strip() if target_num.isdigit(): target_num = int(target_num) target_shop_car = good_list[choice] target_good_name = target_shop_car[0] target_good_price = target_shop_car[1] if target_good_name not in temp_shop_car: temp_shop_car[target_good_name] = [target_num, target_good_price] else: temp_shop_car[target_good_name][0] += target_num else: print('商品数量必须是纯数字') @login_auth def clear_shop_car(): file_path = os.path.join(db_dir, f"{is_login.get('username')}.json") with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) balance = user_dict.get('balance') shop_car = user_dict.get('shop_car') total_money = 0 if len(shop_car) == 0: print('购物车没有数据,请先添加') return for good_num, good_price in shop_car.values(): total_money += good_price * good_num if balance > total_money: user_dict['balance'] -= total_money user_dict['shop_car'] = {} with open(file_path, 'w', encoding='utf8') as f: json.dump(user_dict, f, ensure_ascii=False) print(f'今日消费{total_money}') return else: target_num = input('余额不足是否充值(y/n)>>>:').strip() if target_num == 'y': top_up() return else: print('下次继续') @login_auth def check_shop_car(): file_path = os.path.join(db_dir, '%s.json' % is_login.get('username')) with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) shop_car = user_dict.get('shop_car') # {"挂壁面": [20, 3], "土耳其土豆": [20, 999]} print('购物车信息'.center(27, '*')) for good_name in shop_car: print(f""" 商品名称:{good_name} 商品数量:{shop_car.get(good_name)[0]} 商品单价:{shop_car.get(good_name)[1]} """) print('end'.center(30, '*')) @login_auth def delete_good_name(): file_path = os.path.join(db_dir, '%s.json' % is_login.get('username')) with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) # # {"挂壁面": [20, 3], "土耳其土豆": [20, 999]} shop_car = user_dict.get('shop_car') while True: shop_car_info = list(shop_car.items()) for i, j in enumerate(shop_car_info): print(f"商品编号:{i} | 商品名称:{j[0]} | 商品数量:{j[1][0]} | 商品单价:{j[1][1]} ") delete_id = input('请输入您要删除的商品编号按(q)退出>>>:').strip() if delete_id == 'q': break if delete_id.isdigit(): delete_id = int(delete_id) if delete_id in range(len(shop_car_info)): delete_name = shop_car_info[delete_id][0] shop_car.pop(delete_name) user_dict['shop_car'] = shop_car with open(file_path, 'w', encoding='utf8') as f1: json.dump(user_dict, f1, ensure_ascii=False) else: print('没有该商品编号') else: print('商品编号必须是纯数字') @login_auth def alter_num(): file_path = os.path.join(db_dir, '%s.json' % is_login.get('username')) with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) shop_car = user_dict.get('shop_car') # {"挂壁面": [20, 3], "土耳其土豆": [20, 999]} if len(shop_car) == 0: print('没有商品,无法修改') return while True: shop_car_info = list(shop_car.items()) for i, j in enumerate(shop_car_info): print(f"商品编号:{i} | 商品名称:{j[0]} | 商品数量:{j[1][0]} | 商品单价:{j[1][1]} ") target_id = input('请输入要修改的商品编号>>>:').strip() if not target_id.isdigit(): print('商品编号必须是纯数字') return target_id = int(target_id) if target_id not in range(len(shop_car_info)): print('没有该商品,无法修改') return target_num = input('请输入修改的数量>>>:').strip() if not target_num.isdigit(): print('数量必须是纯数字') return target_num = int(target_num) if target_num == 0: shop_car.pop(shop_car_info[target_id][0]) user_dict['shop_car'] = shop_car with open(file_path, 'w', encoding='utf8') as f1: json.dump(user_dict, f1, ensure_ascii=False) print(f'商品数量已更改为{target_num}') continue shop_car_info[target_id][1][0] = target_num target_name = shop_car_info[target_id][0] shop_car[target_name][0] = target_num user_dict['shop_car'] = shop_car with open(file_path, 'w', encoding='utf8') as f1: json.dump(user_dict, f1, ensure_ascii=False) print(f'商品数量已更改为{target_num}') @login_auth def top_up(): file_path = os.path.join(db_dir, '%s.json' % is_login.get('username')) with open(file_path, 'r', encoding='utf8') as f: user_dict = json.load(f) balance = user_dict.get('balance') new_balance = input('请输入充值金额>>>:').strip() if not new_balance.isdigit(): print('充值金额必须是纯数字') return new_balance = int(new_balance) balance += new_balance user_dict['balance'] = balance with open(file_path, 'w', encoding='utf8') as f1: json.dump(user_dict, f1, ensure_ascii=False) print(f'今日充值{new_balance} 余额为{balance}') func_dict = { '1': register, '2': login, '3': add_shop_car, '4': clear_shop_car, '5': check_shop_car, '6': delete_good_name, '7': alter_num, '8': top_up, '9': user_switch } while True: print(""" 0 退出 1 注册 2 登入 3 添加购物车 4 结算购物车 5 查看购物车 6 删除商品 7 修改商品数量 8 充值 9 切换用户 """) choice = input('请选择功能编号>>>:').strip() if choice == '0': break if not choice.isdigit(): print('功能编号必须是数字') continue if choice in func_dict: func_dict[choice]() else: print('没有该功能编号')