2. 正则表达式

2.1 概述

  • 学习动机

  1. 文本数据处理已经成为常见的编程工作之一

  2. 对文本内容的搜索,定位,提取是逻辑比较复杂的工作

  3. 为了快速方便的解决上述问题,产生了正则表达式技术

  • 定义

即文本的高级匹配模式,其本质是由一系列字符和特殊符号构成的字串,这个字串即正则表达式。

  • 原理

通过普通字符和有特定含义的字符,来组成字符串,用以描述一定的字符串规则,比如:重复,位置等,来表达某类特定的字符串,进而匹配。

  • 学习目标

  1. 熟练掌握正则表达式元字符

  2. 能够读懂常用正则表达式,编辑简单的正则规则

  3. 能够熟练使用re模块操作正则表达式

2.2 元字符使用

  • 普通字符

匹配规则:每个普通字符匹配其对应的字符

e.g.
In : re.findall('ab',"abcdefabcd")
Out: ['ab', 'ab']

注意:正则表达式在python中也可以匹配中文

  • 或关系

元字符: |

匹配规则: 匹配 | 两侧任意的正则表达式即可

e.g.
In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']
In : re.findall("ab|bc","abcabc")
Out: ['ab', 'ab']
注意:已经匹配过的字符不再重新匹配
  • 匹配单个字符

元字符:.

匹配规则:匹配除换行外的任意一个字符

e.g.
In : re.findall('张.丰',"张三丰,张四丰,张五丰")
Out: ['张三丰', '张四丰', '张五丰']
  • 匹配字符集

元字符: [字符集]

匹配规则: 匹配字符集中的任意一个字符

表达形式:

[aeiou你我他] 表示 [] 中的任意一个字符 [0-9],[a-z],[A-Z] 表示区间内的任意一个字符 [_#?0-9a-z] 混合书写,一般区间表达写在后面

e.g.
In : re.findall('[aeiou]',"How are you!")
Out: ['o', 'a', 'e', 'o', 'u']
  • 匹配字符集反集

元字符:[^字符集]

匹配规则:匹配除了字符集以外的任意一个字符

e.g.
In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']

进入灵魂:与前面的字符搭配出现几次

  • 匹配字符重复

元字符: *

匹配规则:匹配前面的一个字符出现0次或多次(>=1)

e.g.
In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']

元字符:+

匹配规则: 匹配前面的字符出现1次或多次

e.g.
In : re.findall('[A-Z][a-z]+',"Hello World")
Out: ['Hello', 'World']

元字符:?

匹配规则: 匹配前面的字符出现0次或1次

e.g. 匹配整数
In [28]: re.findall('-?[0-9]+',"Jame,age:18, -26")
Out[28]: ['18', '-26']

元字符:{n}

匹配规则: 匹配前面的字符出现n次

e.g. 匹配手机号码
In : re.findall('1[0-9]{10}',"Jame:13886495728")
Out: ['13886495728']

元字符:{m,n}

匹配规则: 匹配前面的字符出现m-n次

e.g. 匹配qq号
In : re.findall('[1-9][0-9]{5,10}',"Baron:1259296994")
Out: ['1259296994']

位置匹配开始

  • 匹配字符串开始位置

元字符: ^

匹配规则:匹配目标字符串的开头位置(一个字符串只有一个开头或结尾位置)

e.g.
In : re.findall('^Jame',"Jame,hello")
Out: ['Jame']
  • 匹配字符串的结束位置

元字符: $

匹配规则: 匹配目标字符串的结尾位置

e.g.
In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']

规则技巧: ^$必然出现在正则表达式的开头和结尾处。如果两者同时出现,则中间的部分必须匹配整个目标字符串的全部内容。

通过正则表达式验证一个密码是否为数字字母下划线构成,并且是 6-12位 In [56]: re.findall('^[ _0-9a-zA-Z]{6,12}$',"tedu_0321") Out[56]: ['tedu_0321']

  • 匹配任意(非)数字字符

元字符: \d(等价于[0-9]) \D (等价于[^0-9])

匹配规则:\d 匹配任意数字字符,\D 匹配任意非数字字符

e.g. 匹配端口
In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']
In :re.findall('\D{1,5}',"Mysql: 3306, http:80")
Out[35]: ['Mysql', ': ', ', htt', 'p:']
  • 匹配任意(非)普通字符

元字符: \w \W

匹配规则: \w 匹配普通字符,\W 匹配非普通字符

说明: 普通字符指数字,字母,下划线,汉字,万国字。非普通字符:标点符号,空格等

e.g.
In : re.findall('\w+',"server_port = 8888")
Out: ['server_port', '8888']
In [19]: re.findall('\W+',"server_port = 8888")
Out[19]: [' = ']
​
  • 匹配任意(非)空字符

元字符: \s \S

匹配规则:\s匹配空字符,\S 匹配非空字符

说明:空字符指 空格\r \n \t \v \f 字符 其余均是非空字符

e.g.
In : re.findall('\w+\s+\w+',"hello    world")
Out: ['hello    world']
  • 匹配(非)单词的边界位置

元字符:\b \B

匹配规则:\b 表示单词边界,\B 表示非单词边界

说明:单词边界指数字字母(汉字)下划线与其他字符的交界位置。

e.g.
In : re.findall(r'\bis\b',"This is a test.") 通过r表达元字符的边界含义,而不是字符串退格含义
Out: ['is']

注意: 当元字符符号与Python字符串中转义字符冲突的情况则需要使用r将正则表达式字符串声明为原始功能字符串,如果不确定那些是Python字符串的转义字符,则可以在所有正则表达式前加r。因此实际开发可以无脑加r

类别 元字符
匹配字符 . [...] [^...] \d \D \w \W \s \S
匹配重复 * + ? {n} {m,n}
匹配位置 ^ $ \b \B
其他 | () \

2.3 匹配规则

2.3.1 特殊字符匹配

  • 目的 : 如果匹配的目标字符串中包含正则表达式特殊字符,则在表达式中元字符就想表示其本身含义时就需要进行 \ 处理。

    特殊字符: . * + ? ^ $ [] () {} | \
  • 操作方法:在正则表达式元字符前加 \ 则元字符就是去其特殊含义,就表示字符本身

e.g. 匹配特殊字符 . 时使用 \. 表示本身含义
​
In : re.findall('-?\d+\.?\d+',"123,-123,1.23,-1.23")
Out: ['123', '-123', '1.23', '-1.23']
​
In [4]: re.findall('\$\d+',"日薪: $150")
Out[4]: ['$150']

2.3.2 贪婪模式和非贪婪模式

  • 定义 贪婪模式: 默认情况下这个模式,匹配重复的元字符总是尽可能多的向后匹配内容。

比如: * + ? {m,n}

In [40]: re.findall('ab*',"abbbbbbbbbbbbb") Out[40]: ['abbbbbbbbbbbbb']

In [41]: re.findall('ab+',"abbbbbbbbbbbbb") Out[41]: ['abbbbbbbbbbbbb']

In [42]: re.findall('ab?',"abbbbbbbbbbbbb") Out[42]: ['ab']

非贪婪模式: 让匹配重复的元字符尽可能少的向后匹配内容(在符合规则的前提下)

In [42]: re.findall('ab?',"abbbbbbbbbbbbb") Out[42]: ['ab']

In [43]: re.findall('ab*?',"abbbbbbbbbbbbb") Out[43]: ['a']

In [44]: re.findall('ab+?',"abbbbbbbbbbbbb") Out[44]: ['ab']

In [45]: re.findall('ab{2,6}?',"abbbbbbbbbbbbb") Out[45]: ['abb'] In [47]: re.findall('ab{2,}?c',"abbbbbbbbbbbbbc") Out[47]: ['abbbbbbbbbbbbbc']

  • 贪婪模式转换为非贪婪模式(元字符后面加?即可)

    In [48]: re.findall('ab.*c',"abbcbbbbbbbbbbbc") Out[48]: ['abbcbbbbbbbbbbbc']

    In [49]: re.findall('ab.*?c',"abbcbbbbbbbbbbbc") Out[49]: ['abbc']

在对应的匹配重复的元字符后加 '?' 号即可

*  ->  *?
+  ->  +?
?  ->  ??
{m,n} -> {m,n}?
e.g.
In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']

2.3.3 正则表达式分组

  • 定义

在正则表达式中,以()建立正则表达式的内部分组,子组是正则表达式的一部分,作为内部整体操作对象

In [116]: re.findall("张小亮:(\d+)","王小明:89,张小亮:91,李晓彤:79")
Out[116]: ['91']
#findall函数特征决定结果只显示符号字符串的子组内容
  • 作用 : 可以被作为整体操作,改变元字符的操作对象

e.g.  改变 +号 重复的对象
In : re.search(r'(ab)+',"ababababab").group()
Out: 'ababababab'
​
e.g. 改变 |号 操作对象
In : re.search(r'(王|李)\w{1,3}',"王者荣耀,李者荣耀").group()
Out: '王者荣耀'
​
In [52]: re.findall(r'(王|李)\w{1,3}',"王者荣耀")
Out[52]: ['王']
  • 捕获组

捕获组本质也是一个子组,只不过拥有一个名称用以表达该子组的意义,这种有名称的子组即为捕获组。

格式:(?P<name>pattern)

e.g. 给子组命名为 "pig"
In : re.search(r'(?P<pig>ab)+',"ababababab").group('pig')
Out: 'ab'
功能上相同,只不过给子组起一个名字增加可读性
In : re.search(r'ab',"ababababab").group()
Out: 'ab'
  • 注意事项

  • 一个正则表达式中可以包含多个子组

  • 子组可以嵌套但是不宜结构过于复杂

  • 子组序列号一般从外到内,从左到右计数

2.3.4 正则表达式匹配原则

  1. 正确性,能够正确的匹配出目标字符串.

  2. 排他性,除了目标字符串之外尽可能少的匹配其他内容.

  3. 全面性,尽可能考虑到目标字符串的所有情况,不遗漏.

  4. 可以进行二次程序筛选,在第一次匹配不够精确情况下

2.4 Python re模块使用

2.4.1 基础函数使用

 re.findall(pattern,string)功能: 根据正则表达式匹配目标字符串内容参数: pattern  正则表达式string 目标字符串返回值: 匹配到的内容列表,如果正则表达式有子组则只能获取到子组对应的内容,无法获取匹配到的整个串:即使知道整个串符合条件也只给你显示整个串的符合子组条件串。
 re.split(pattern,string,max)功能: 使用正则表达式匹配内容,切割目标字符串参数: pattern  正则表达式string 目标字符串max 最多切割几部分返回值: 切割后的内容列表
 re.sub(pattern,replace,string,count)功能: 使用一个字符串替换正则表达式匹配到的内容参数: pattern  正则表达式replace  替换的字符串string 目标字符串count  最多替换几处,默认替换全部返回值: 替换后的字符串
"""re 模块示例
"""
import re
​
str01 = "Alex:1998,Sunny:1999"
​
# 使用正则表达式匹配字符串,将匹配到的内容替换为##,替换2处
result = re.sub("\W+","##",str01,2)
print(result)
​
# 使用正则表达式匹配的部分分割字符串,分割两处
# result = re.split("\W+",str01,2)
# print(result)
​
# 如果正则表达式有子组则只能得到子组对应的部分
# result = re.findall("(\w+):(\d+)",str01)
# print(result)
​
​

2.4.2 生成match对象

以上是匹配完字符串直接返回匹配内容,这里匹配的内容不直接给你,通过创建match对象给你返回回来。即在匹配内容同时给你更多信息,例如告诉你在哪个位置匹配上的。

 re.finditer(pattern,string)功能: 根据正则表达式匹配目标字符串内容参数: pattern  正则表达式string 目标字符串返回值: 匹配结果的迭代器re.match(pattern,string)
功能:匹配某个目标字符串开始位置
参数:pattern 正则string  目标字符串
返回值:匹配内容match object
​
​
re.search(pattern,string)
功能:匹配目标字符串第一个符合内容
参数:pattern 正则string  目标字符串
返回值:匹配内容match object

2.4.3 match对象使用

  • span() 获取匹配内容的位置(即目标字符串的切片位置)

  • group(n = 0)

    功能:获取match对象匹配内容

    参数:默认为0表示获取整个match对象内容,如果是序列号或者组名则表示获取对应子组内容

    返回值:匹配字符串

    """正则表达式示例
    """
    import re
    ​
    str01 = "Alex:1998,Sunny:1999"
    ​
    # 只能匹配第一处符合规则内容
    result = re.search("(\w+):(?P<year>\d+)", str01)
    print(result.group(1))  # 组编号
    print(result.group("year"))  # 组名
    ​
    #匹配开头位置,相当于自动加上^符号哦
    result = re.match("\w+",str01)
    print(result.group())
    ​
    ​
    # 返回可迭代对象
    result = re.finditer("\w+", str01)
    for item in result:print(item)  # match对象 —— 一个match对象对应一处匹配内容print("位置:", item.span())print("内容:", item.group())
    ​

"""
文件处理综合训练 : 使用提供的inet.log完成
​
设计程序,运行程序后输入 一个接口名称
得到这个接口运行情况当中的 address is
的值
比如:运行程序后输入 BVI100 则得到 10f3.116c.e6a7
提示: 要考虑到用户输入的接口不存在的情况每段之间有空行每段的首个单词就是接口名称
"""
​
"""思路:通过输入,获取所在段落,
"""
import re
​
​
# 生成器:每次提供一段内容
def every_duan():  # 获取每段内容file = open("inet.log", "r")while True:  # 循环一次获取一段内容data = ""for line in file:if line == '\n':breakdata += lineif data:yield dataelse:return None
​
​
def get_address(port):for data in every_duan():head = re.match("\S+", data).group()if head == port:address = re.search("([0-9a-f]{4}\.?){3}", data)return address.group()return "not found"
​
​
if __name__ == '__main__':port = input("请输入接口名称")print(get_address(port))

4.txt

前情回顾
​
1. 文件 和 字节串文件 : 文本   二进制字节串 : bytes    encode()   decode()
​
2. 文件操作
​open() --> read()/write() -> close()
​r  w  a  +  b
​
3. 缓冲区  文件偏移量
​缓冲区 : flush()   设置缓冲buffering
​偏移量 : seek()
​
4. os 模块
​os.path.getsize()os.listdir()
​
正则表达式匹配训练
​
1. 请在下面字符串中匹配出所有数字今天是 2021年3月30日
​
In [25]: re.findall('[0-9]+','今天是2021年3月30日...: ')
Out[25]: ['2021', '3', '30']
​
​
2. 使用一个正则表达式匹配一段英文当中所有
以大写字母开头的单词
In [27]: re.findall('[A-Z][a-z]*',"How are you,Ja...: me")
Out[27]: ['How', 'Jame']
​
3. 在下面字符串中匹配数字
​
-12°的气温,战士背着30Kg重装备。
In [33]: re.findall('-?[0-9]+',"-12°的气温,战士...: 背着30Kg重装备。")
Out[33]: ['-12', '30']
​
4. 匹配国内手机号码
​
In [81]: re.findall(r'\b1[3-9][0-9]{9}\b',"电话:1...: 3838386767,卡号:699915788492384747")
Out[81]: ['13838386767']
​
​
​
5. 匹配qq号码
​
In [43]: re.findall('[1-9][0-9]{4,10}',"125929699...: 4")
Out[43]: ['1259296994']
​
​
6. 通过正则表达式验证一个密码是否
为数字字母下划线构成,并且是 6-12位
In [56]: re.findall('^[_0-9a-zA-Z]{6,12}$',"tedu_...: 0321")
Out[56]: ['tedu_0321']
​
​
7. 匹配一组数字  -12  30  1.25  -3.6
In [92]: re.findall(r'-?\d+\.?\d*',"-12  30  1.25...:   -3.6  5")
Out[92]: ['-12', '30', '1.25', '-3.6', '5']
​
8. 匹配 每天薪资日薪: $150
​
In [94]: re.findall(r'\$\d+',"日薪: $150")
Out[94]: ['$150']
​
​
9. 匹配出如下字符串中图书的名字包含书名号
​张xx :《活着 —— 记录》 《北京, 2021》李xx :《奥特曼 打小怪兽 ~~ biubiu》王xx :《宇宙危机 @ 叔叔救我》
​
In [111]: re.findall("《.+?》",str01)
Out[111]: ['《活着 —— 记录》', '《北京, 2021》', '《奥特曼 打小怪兽 ~~ biubiu》', '《宇宙危机 @ 叔叔救我》']
​
​
10. 有一个字符串如下,匹配出张小亮分数
​王小明:89 ,张小亮:91,李晓彤:79
​
In [116]: re.findall("张小亮:(\d+)","王小明:89...: ,张小亮:91,李晓彤:79")
Out[116]: ['91']
​
​
11. 匹配一个 IP地址
​ip:192.168.4.45
​
In [125]: re.search(r'(\d{1,3}\.?){4}',"ip:192.16...: 8.4.45").group()
Out[125]: '192.168.4.45'
​
​
12. 匹配身份证号
​
文件处理综合训练 : 使用提供的inet.log完成
​
设计程序,运行程序后输入 一个接口名称
得到这个接口运行情况当中的 address is
的值
比如:运行程序后输入 BVI100 则得到 10f3.116c.e6a7
提示: 要考虑到用户输入的接口不存在的情况每段之间有空行每段的首个单词就是接口名称
​
​
作业: 正则表达式和文件处理总结
​
​
​
"""
home022. 编写一个函数,传入一个目录(假设该目录中全是文本文件),函数的功能是将这些文本文件合并为一个大文件,大文件目录是当前路径的下home文件夹下的fileall文件
​def union_files(dir):pass
"""
import os
​
​
def union_files(dir):fw = open("./home/file_all.txt", 'w')for file in os.listdir(dir):fr = open("./home/" + file, 'r')while True:  # 循环边读边写,效率更高data = fr.read(1024)if not data:breakfw.write(data)fr.close()fw.close()
​
​
union_files("./home")
​
"""文件存储数据与正则表达式拓展实现
"""
import re  # 导入正则表达式模块
import os  # 导入操作系统模块
​
filename = "students.txt"  # 定义保存学生信息的文件名
​
​
def menu():# 输出菜单print('''╔———————学生信息管理系统————————╗│                                              ││   =============== 功能菜单 ===============   ││                                              ││   1 录入学生信息                             ││   2 查找学生信息                             ││   3 删除学生信息                             ││   4 修改学生信息                             ││   5 排序                                     ││   6 统计学生总人数                           ││   7 显示所有学生信息                         ││   0 退出系统                                 ││  ==========================================  ││  说明:通过数字键选择菜单          │╚———————————————————————╝''')
​
​
def main():ctrl = True  # 标记是否退出系统while ctrl:menu()  # 显示菜单option = input("请选择:")  # 选择菜单项option_str = re.sub("\D", "", option)  # 提取数字if option_str in ['0', '1', '2', '3', '4', '5', '6', '7']:if option_str == '0':  # 退出系统print('您已退出学生成绩管理系统!')ctrl = Falseelif option_str == '1':  # 录入学生成绩信息insert()elif option_str == '2':  # 查找学生成绩信息search()elif option_str == '3':  # 删除学生成绩信息delete()elif option_str == '4':  # 修改学生成绩信息modify()elif option_str == '5':  # 排序sort()elif option_str == '6':  # 统计学生总数total()elif option_str == '7':  # 显示所有学生信息show()
​
​
'''1 录入学生信息'''
​
​
def insert():stdentList = []        # 保存学生信息的列表mark = True  # 是否继续添加while mark:id = input("请输入ID(如 1001):")if not id:  # ID为空,跳出循环breakname = input("请输入名字:")if not name:  # 名字为空,跳出循环breaktry:english = int(input("请输入英语成绩:"))python = int(input("请输入Python成绩:"))c = int(input("请输入C语言成绩:"))except:print("输入无效,不是整型数值....重新录入信息")continuestdent = {"id": id, "name": name, "english": english, "python": python, "c": c}  # 将输入的学生信息保存到字典stdentList.append(stdent)  # 将学生字典添加到列表中inputMark = input("是否继续添加?(y/n):")if inputMark == "y":  # 继续添加mark = Trueelse:  # 不继续添加mark = Falsesave(stdentList)  # 将学生信息保存到文件print("学生信息录入完毕!!!")
​
​
# 将学生信息保存到文件
def save(student):try:students_txt = open(filename, "a")  # 以追加模式打开except Exception as e:students_txt = open(filename, "w")  # 文件不存在,创建文件并打开for info in student:students_txt.write(str(info) + "\n")  # 按行存储,添加换行符students_txt.close()  # 关闭文件
​
​
'''2 查找学生成绩信息'''
​
​
def search():mark = Truestudent_query = []  # 保存查询结果的学生列表while mark:id = ""name = ""if os.path.exists(filename):  # 判断文件是否存在mode = input("按ID查输入1;按姓名查输入2:")if mode == "1":id = input("请输入学生ID:")elif mode == "2":name = input("请输入学生姓名:")else:print("您的输入有误,请重新输入!")continue  # 重新查询with open(filename) as file:  # 打开文件student = file.readlines()  # 读取全部内容for list in student:d = dict(eval(list))  # 字符串转字典if id is not "":  # 判断是否按ID查if d['id'] == id:student_query.append(d)  # 将找到的学生信息保存到列表中elif name is not "":  # 判断是否按姓名查if d['name'] == name:student_query.append(d)  # 将找到的学生信息保存到列表中show_student(student_query)  # 显示查询结果student_query.clear()  # 清空列表inputMark = input("是否继续查询?(y/n):")if inputMark == "y":mark = Trueelse:mark = Falseelse:print("暂未保存数据信息...")return
​
​
'''3 删除学生成绩信息'''
​
​
def delete():mark = True  # 标记是否循环while mark:studentId = input("请输入要删除的学生ID:")if studentId is not "":  # 判断要删除的学生是否存在if os.path.exists(filename):  # 判断文件是否存在with open(filename, 'r') as rfile:  # 打开文件student_old = rfile.readlines()  # 读取全部内容else:student_old = []ifdel = False  # 标记是否删除if student_old:  # 如果存在学生信息with open(filename, 'w') as wfile:  # 以写方式打开文件d = {}  # 定义空字典for list in student_old:d = dict(eval(list))  # 字符串转字典if d['id'] != studentId:wfile.write(str(d) + "\n")  # 将一条学生信息写入文件else:ifdel = True  # 标记已经删除if ifdel:print("ID为 %s 的学生信息已经被删除..." % studentId)else:print("没有找到ID为 %s 的学生信息..." % studentId)else:  # 不存在学生信息print("无学生信息...")break  # 退出循环show()  # 显示全部学生信息inputMark = input("是否继续删除?(y/n):")if inputMark == "y":mark = True  # 继续删除else:mark = False  # 退出删除学生信息功能
​
​
'''4 修改学生成绩信息'''
​
​
def modify():show()  # 显示全部学生信息if os.path.exists(filename):  # 判断文件是否存在with open(filename, 'r') as rfile:  # 打开文件student_old = rfile.readlines()  # 读取全部内容else:returnstudentid = input("请输入要修改的学生ID:")with open(filename, "w") as wfile:  # 以写模式打开文件for student in student_old:d = dict(eval(student))  # 字符串转字典if d["id"] == studentid:  # 是否为要修改的学生print("找到了这名学生,可以修改他的信息!")while True:  # 输入要修改的信息try:d["name"] = input("请输入姓名:")d["english"] = int(input("请输入英语成绩:"))d["python"] = int(input("请输入Python成绩:"))d["c"] = int(input("请输入C语言成绩:"))except:print("您的输入有误,请重新输入。")else:break  # 跳出循环student = str(d)  # 将字典转换为字符串wfile.write(student + "\n")   # 将修改的信息写入到文件print("修改成功!")else:wfile.write(student)  # 将未修改的信息写入到文件mark = input("是否继续修改其他学生信息?(y/n):")if mark == "y":modify()  # 重新执行修改操作
​
​
'''5 排序'''
​
​
def sort():show()  # 显示全部学生信息if os.path.exists(filename):  # 判断文件是否存在with open(filename, 'r') as file:  # 打开文件student_old = file.readlines()  # 读取全部内容student_new = []for list in student_old:d = dict(eval(list))  # 字符串转字典student_new.append(d)  # 将转换后的字典添加到列表中else:returnascORdesc = input("请选择(0升序;1降序):")if ascORdesc == "0":  # 按升序排序ascORdescBool = False           # 标记变量,为False表示升序排序elif ascORdesc == "1":  # 按降序排序ascORdescBool = True          # 标记变量,为True表示降序排序else:print("您的输入有误,请重新输入!")sort()  mode = input("请选择排序方式(1按英语成绩排序;2按Python成绩排序;3按C语言成绩排序;0按总成绩排序):")if mode == "1":  # 按英语成绩排序student_new.sort(key=lambda x: x["english"], reverse=ascORdescBool)elif mode == "2":  # 按Python成绩排序student_new.sort(key=lambda x: x["python"], reverse=ascORdescBool)elif mode == "3":  # 按C语言成绩排序student_new.sort(key=lambda x: x["c"], reverse=ascORdescBool)elif mode == "0":  # 按总成绩排序student_new.sort(key=lambda x: x["english"] + x["python"] + x["c"], reverse=ascORdescBool)else:print("您的输入有误,请重新输入!")sort()show_student(student_new)  # 显示排序结果
​
​
''' 6 统计学生总数'''
​
​
def total():if os.path.exists(filename):  # 判断文件是否存在with open(filename, 'r') as rfile:  # 打开文件student_old = rfile.readlines()  # 读取全部内容if student_old:print("一共有 %d 名学生!" % len(student_old))else:print("还没有录入学生信息!")else:print("暂未保存数据信息...")
​
​
''' 7 显示所有学生信息 '''
​
​
def show():student_new = []if os.path.exists(filename):  # 判断文件是否存在with open(filename, 'r') as rfile:  # 打开文件student_old = rfile.readlines()  # 读取全部内容for list in student_old:student_new.append(eval(list))  # 将找到的学生信息保存到列表中if student_new:show_student(student_new)else:print("暂未保存数据信息...")
​
​
# 将保存在列表中的学生信息显示出来
def show_student(studentList):if not studentList:print("(o@.@o) 无数据信息 (o@.@o) \n")returnformat_title = "{:^6}{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^10}"print(format_title.format("ID", "名字", "英语成绩", "Python成绩", "C语言成绩", "总成绩"))format_data = "{:^6}{:^12}\t{:^12}\t{:^12}\t{:^12}\t{:^12}"for info in studentList:print(format_data.format(info.get("id"), info.get("name"), str(info.get("english")), str(info.get("python")),str(info.get("c")),str(info.get("english") + info.get("python") + info.get("c")).center(12)))
​
​
if __name__ == "__main__":main()
​

Python-Level2-day04:正则表达式概述,元字符使用,匹配规则(特殊字符匹配,贪与非贪婪模式,分组),re模块使用相关推荐

  1. python与正则表达式(part3)--贪婪模式和非贪婪模式

    文章目录 贪婪模式和非贪婪模式 定义 贪婪模式转换为非贪婪模式 贪婪模式和非贪婪模式 定义 贪婪模式: 默认情况,在整个表达式匹配成功的前提下,尽可能多的匹配. 非贪婪模式(懒惰模式): 在整个表达式 ...

  2. 正则表达式口诀及常用正则 。正则贪婪与非贪婪模式

    正则表达式口诀及常用正则 签于网上太多的介绍都是一篇凶悍的短文,边看边理解可以,帮助记忆不行.又受五笔字型字根表口诀"白手看头三二斤..."的启发,  试作"正则表达式助 ...

  3. 正则表达式之 贪婪与非贪婪模式详解

    1 概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配.非贪婪模式只被部分NF ...

  4. 转:正则表达式之 贪婪与非贪婪模式详解

    1 概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配.非贪婪模式只被部分NF ...

  5. python 正则表达式 re (.*?)和(.*)的区别(贪婪模式非贪婪模式)惰性匹配

    贪婪模式 .* 非贪婪模式 .*? 1. .匹配任意除换行符"\n"外的字符: 2. *表示匹配前一个字符0次或无限次: 3. +或*后跟?表示非贪婪匹配,即尽可能少的匹配,如*? ...

  6. 第11.9节 Python正则表达式的贪婪模式和非贪婪模式

    在使用正则表达式时,匹配算法存在贪婪模式和非贪婪模式两种模式,在<第11.8节 Pytho正则表达式的重复匹配模式及元字符"?". "*". " ...

  7. python 正则表达式贪婪模式与非贪婪模式

    1 贪婪模式与非贪婪模式 的理解 1.1 贪婪模式: 是尽可能的多地匹配字符 ,贪婪模式一般是在元符号后面没有添加? 1.2 非贪婪模式(懒惰模式): 是尽可能的少匹配字符,非贪婪模式一般是元符号后面 ...

  8. python贪婪匹配_python re模块匹配贪婪和非贪婪模式详解

    python re模块匹配贪婪和非贪婪模式详解 这篇文章主要介绍了python re模块匹配贪婪和非贪婪模式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友 ...

  9. python 正则表达式 非贪婪,python中如何使用正则表达式的非贪婪模式示例

    前言 本文主要给大家介绍了关于python使用正则表达式的非贪婪模式的相关内容,分享出来供大家参考学习,下面话不多说了,来一起详细的介绍吧. 在正则表达式里,什么是正则表达式的贪婪与非贪婪匹配 如:S ...

  10. java 正则表达式 非贪婪模式_正则表达式的贪婪模式和非贪婪模式

    一.什么是贪婪模式和非贪婪模式? 定义 贪婪模式:正则表达式趋向于匹配最大长度. 非贪婪模式:正则表达式趋向于匹配最小长度,即一旦匹配到结果就结束. 如何区分? 默认是贪婪模式. 若 量词 后面添加 ...

最新文章

  1. .NET之全平台一体化的体验
  2. 阿里云引领云原生进化,智能、互联、可信三位一体
  3. ISSET_SE 错误异常
  4. read name 和 read 在 Bash 中的区别
  5. hbase的2.2.4版本支持哪个版本的hadoop_Hadoop 2.7 不停服升级到 3.2 在滴滴的实践
  6. 砥志研思SVM(四) 序列最小最优化算法(SMO)论文翻译
  7. sqlserver 清除日志
  8. mysql5.5源码安装_MySQL5.5源码安装
  9. 姚期智院士亲自讲授,一文读懂量子计算
  10. 从SharePoint 2013迁移到SharePoint Online - 评估工具
  11. md5util java_Java 工具类 - MD5Util
  12. java web项目个人博客_javaWeb项目个人博客系统
  13. Vi 编辑器常用命令
  14. SAP培训及ABAP学习入门必读
  15. 一个快播倒下去,千千万万个快播站起来
  16. 如何进行探索性数据分析
  17. wago edz 下载_用电子枪制造的WeakAuras Wago.io桥
  18. Python数据分析理论与实战完整版本
  19. source setup.bash 文件
  20. winrar 百度网盘_不冲百度网盘会员,如何在手机上打开网盘里的压缩包?

热门文章

  1. 操作系统 FCFS,SPF,HRRN算法的实现
  2. 二十一个心理学效应 笔记
  3. matlab仿真放入直流电源,用Matlab/Simulink软件包建模电容滤波直流电源
  4. 信度spss怎么做_Spss详细图文教程——问卷信度和效度检验步骤图解
  5. 618的优惠券去哪了?
  6. 你真的搞懂Class,class了么?
  7. html怎样使字数占相同位,《古对今》教案
  8. ​怎么判断是前端bug还是后端bug?
  9. 入门系列- ABP 本地化
  10. word毕业论文格式排版修改