定制设计详解Python正则表达式(含丰富案例)

前言:定制设计定制设计正则表达式在、定制设计数据分析中有着广泛使用,定制设计掌握正则表达式能够达定制设计到事半功倍的效果。定制设计本文详细介绍正则表达定制设计式中各种规则及其符号含义,并结合Python中的Re定制设计库进行演示,由浅入深,定制设计即学即练即用,内容丰富,定制设计非常适合初学者。

正则表达式(regular expression)定制设计就是用一组由字母和符号组成的“表达式”定制设计来描述一个特征,定制设计然后去验证另一个“字符串”定制设计是否符合这个特征。定制设计比如表达式“xy+” 定制设计描述的特征是“一个 ‘x’ 和 至少一个 ‘y' ”,那么‘xy',‘xyy', ‘xyyyyyyy'定制设计都符合这个特征。

定制设计正则表达式主要应用场景

  • 定制设计验证字符串是否符合指定特征,定制设计比如验证用户名或密码定制设计是否符合要求、定制设计是否是合法的邮件地址等;

  • 定制设计用来查找字符串,定制设计从一个长的文本中查找定制设计符合指定特征的字符串,定制设计比查找固定字符串更加灵活方便;

  • 用来替换,定制设计比普通的替换更强大。

正则表达式的规则

(1)普通字符

字母、数字、汉字、下划线、以及没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。

例1:表达式 “c”,在匹配字符串 “abcde” 时,匹配结果是:成功;匹配到的内容是:“c”;匹配到的位置是:开始于2,结束于3。(包含开始位置,不包含结束位置

例2:表达式 "bcd",在匹配字符串"abcde"时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。

(2)转义字符

  • 一些不便书写的字符,采用在前面加“\” 的方法。例如制表符、换行符等;

  • 一些有特殊用处的标点符号,在前面加“\” 后,代表该符号本身。例如{,}, [, ], /, \, +, *, ., $, ^, |, ? 等;

转义字符的匹配方法与“普通字符”类似,也是匹配与之相同的一个字符。

例如:表达式 "\$d",在匹配字符串 "abc$de" 时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于3,结束于5。

(3)能够与 '多种字符' 匹配的表达式

正则表达式中的一些表示方法,可以匹配 ‘多种字符’ 中的任意一个字符。例如,表达式"\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。

例如:表达式 "\d\d",在匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。

(4)自定义能够匹配 '多种字符' 的表达式

使用方括号 [ ] 包含一系列字符,能匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能匹配其中字符之外的任意一个字符。虽然可以匹配其中任意一个,但是只能是一个,不是多个。

例如:表达式 "[bcd][bcd]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。

(5)修饰匹配次数的特殊符号

例如:表达式 "\d+\.?\d*" 在匹配 "It costs $12.5" 时,匹配的结果是:成功;匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。

(6)一些代表抽象意义的特殊符号

例1:表达式 "^aaa" 在匹配 "xxxaaaxxx" 时,匹配失败。因为 "^" 要求与字符串开始的地方匹配,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配,比如:"aaaxxxxxx"。

例2:表达式 "aaa$"在匹配 "xxxaaaxxx" 时,匹配失败。因为"$" 要求与字符串结束的地方匹配,只有当"aaa"位于字符串的结尾的时候,"aaa$"才能匹配,比如:"xxxxxxaaa"。

例3:表达式 "Tom|Jack"在匹配字符串 "I'mTom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。

例4:表达式 "(go\s*)+"在匹配 "Let'sgo gogo!"时,匹配结果是:成功;匹配到内容是:"gogogo";匹配到的位置是:开始于6,结束于14。

例5:表达式 "¥(\d+\.?\d*)"在匹配 "$10.9,¥20.5"时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。

思考题:写出满足下列要求的正则表达式

  • 仅含6位数字的字符串  

  • 18位身份证号码(最后一位可能包含X)

  • 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)

匹配次数中的贪婪与非贪婪

在使用修饰匹配次数的特殊符号时,如“?”,“*”, “+”等,可以使同一个表达式能够匹配不同的次数,具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配,这种匹配原则就叫作"贪婪" 模式 。例如,针对文本“dxxxdxxxd”,下列表达式匹配结果如下。

在修饰匹配次数的特殊符号后再加上一个"?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作"非贪婪" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。例如,针对文本“dxxxdxxxd”,下列表达式匹配结果如下。

Python中的正则表达式库 - re

  • re库是Python的标准库,不需要额外安装,主要用于字符串匹配

  • 调用方式:import re

  • re 库采用raw string类型表示正则表达式,rawstring是不包含对转义符再次转义的字符串。例如:r'[1‐9]\d{5}’

  • 也可以采用string类型表示正则表达式,但更繁琐,例如“'[1‐9]\\d{5}'”

  • 当正则表达式包含转义符时,建议使用raw string

re库的主要功能函数

注意group()和groups()的区别一个是返回匹配的字符串,一个是返回各部分匹配内容组成的元组。当表达式中没有圆括号时,groups()返回的是空元组,当存在圆括号时,有几个圆括号groups()返回的元组里就有几个元素。

正则表达式案例-验证用户名

编写程序实现下述功能,提示用户输入用户名,要求用户名以字母开头,长度不少于3位,只能包含字母、数字、下划线,如果用户输入符合要求,则提示注册成功,否则提示用户名不符合要求,请重新输入,一直循环直到用户名符合要求为止。程序执行效果如下图所示。

参考代码如下: 

  1. import re # 导入正则表达式库
  2. name = input("请输入用户名,以字母开头,长度不少于3位,只能包含字母、数字、下划线:") # 提示用户输入
  3. match = re.match(r"^[a-zA-Z]\w{2,}$", name) # 验证输入是否符合要求
  4. while match is None: # 如果不符合要求,则循环
  5. print("用户名不符合要求,请重新输入:", end=" ") # 提示用户名不符合要求
  6. name = input() # 重新获取用户输入
  7. match = re.match(r"^[a-zA-Z]\w{2,}$", name) # 验证输入是否符合要求
  8. print("恭喜你, {} ,注册成功!".format(name)) # 提示注册成功

思考:

  • 正则表达式前面的^能够省略?为什么?
  • 有没有其它等价的正则表达式写法?
  • 正则表达式最后的$能否省略?为什么?

正则表达式案例-编程语言排行

  • 数据来源:https://www.tiobe.com/tiobe-index/网页源代码,保存到”编程语言排行.txt”文件。

  • 部分内容截图如下,排行前十的编程语言数据存放在series属性里,每项编程语言包含名称(name)和数据(data)两部分内容,其中data部分包含该编程语言各个月份编程语言所占比例,。

  1. import re # 正则表达式
  2. import csv # csv文件操作
  3. with open("编程语言排行.txt", mode="r", encoding="utf-8") as fp: # 打开指定文件
  4. text = fp.read() # 读取文件内容
  5. content = " ".join(re.findall(r"series: (.*?)\}\);", text, re.DOTALL)) # 获取所有编程语言数据
  6. total_content = re.findall(r"({.*?})", content, re.DOTALL) # 获取各个编程语言的具体数据
  7. with open("lang.csv", mode="w", encoding="utf-8", newline="") as fp: # 对数据进行处理并保存到文件
  8. writer = csv.DictWriter(fp, ['name', 'value', 'date'])
  9. writer.writeheader() # 写入标题
  10. for item in total_content:
  11. name = " ".join(re.findall(r"name : '(.*?)'", item, re.DOTALL))
  12. temp_datas = re.findall(r"\[Date.UTC(.*?)\]", item, re.DOTALL) # 获取不同时间的热度信息
  13. for data in temp_datas:
  14. data = data.replace(" ", "").replace("(", "").replace(")", "")
  15. value = data.split(",")[-1] # 热度值
  16. date = data.split(",")[:-1] # 日期信息
  17. writer.writerow({"name": name, "value": value, "date": "{}-{:02d}-{:02d}".format(date[0], int(date[1]) + 1, int(date[2]))})

部分数据截图效果如下:

完整课件下载网址:

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发