文章目录
- 一、正则表达式基础
- 二、进阶知识
- 三、优秀实践
- 参考资料:
一、正则表达式基础
正则表达式是一种用来描述字符模式的语言,它可以用来匹配、查找、替换字符串中的文本。在Python中,我们可以使用re模块来操作正则表达式。
- 正则表达式基本语法
正则表达式的基本语法如下:
- 字符:一个字符表示匹配该字符本身
- 例如,正则表达式"a"可以匹配字符"a",但不能匹配"a1"或"b"
- 字符集合:用方括号表示一组字符,匹配其中的任意一个字符
- 例如,正则表达式"[ab]“可以匹配字符"a"或"b”,但不能匹配"a1"
- 范围表示:用连字符表示范围,匹配其中的任意一个字符
- 例如,正则表达式"[a-z]“可以匹配任意小写字母,而”[0-9]"可以匹配任意数字
- 预定义字符集合:用特殊的字符表示一组字符,例如\d表示任意数字,\s表示任意空白字符,\w表示任意字母、数字或下划线等等
- 量词:表示前面的字符或组合可以出现的次数
- 例如,正则表达式"a+“可以匹配一个或多个字符"a”,"a*“可以匹配零个或多个字符"a”,“a?“可以匹配零个或一个字符"a”,”{n}“表示匹配恰好n个前面的字符,”{n,m}"表示匹配n到m个前面的字符
- 或:用|表示或者,匹配符合其中任意一种情况的字符串
- 例如,正则表达式"ab|cd"可以匹配"ab"或"cd"
- 分组:用()表示一组字符,其中的内容可以被引用到其他地方
- 例如,正则表达式"(ab)+“可以匹配"ab”、“abab”、"ababab"等
- 使用re模块匹配文本
在Python中,我们可以使用re模块中的findall、search、match等函数来匹配字符串。它们的区别在于findall会返回所有符合条件的结果,而search和match只会返回第一个符合条件的结果。
例如,以下代码可以匹配一个字符串中的所有数字:
``python
import re
text = “hello 123 world 456”
pattern = “\d+”
result = re.findall(pattern, text)
print(result) # [“123”, “456”]
`
- 实战练习
以下是几个正则表达式实战练习:
- 匹配邮箱地址:[\w.]+@\w+.\w+
- 匹配手机号码:1[3456789]\d{9}
- 匹配IP地址:(\d{1,3}.){3}\d{1,3}
- 匹配HTML标签:<([a-z]+)([^<]+)(?:>(.)</\1>|\s+/>)
- 匹配中文字符:[\u4e00-\u9fa5]
二、进阶知识
- 贪婪与非贪婪匹配
默认情况下,正则表达式采用贪婪匹配,即尽可能地匹配更多的字符。例如,正则表达式"\d+“会尽可能匹配到更多的数字字符。如果要采用非贪婪匹配,可以在量词后加上”?“。例如,正则表达式”\d+?"会匹配到最少的数字字符。
- 回溯与性能优化
正则表达式的匹配过程中,可能会出现回溯的情况,即尝试匹配失败后,会回溯到之前的位置重新匹配。如果回溯次数太多,就会导致匹配效率低下。为了避免回溯,可以使用一些优化技巧,例如避免使用多重嵌套的括号、避免使用正则表达式中不必要的量词、采用非贪婪匹配等等。
- 前向匹配和后向匹配
前向匹配和后向匹配是正则表达式中一些高级的功能。它们可以用来指定一个字符串前面或后面必须满足特定的条件才能进行匹配。例如,可以使用前向匹配来匹配一个字符串前面必须包含特定的字符串,例如"前方高能";可以使用后向匹配来匹配一个字符串后面必须包含特定的字符串,例如"后面的话"。
- lookaround
正则表达式中的lookaround功能可以用来实现前向匹配和后向匹配。lookaround其实是一个零宽断言,它不会真正匹配字符串,而只是检查字符串前面或后面是否符合特定的条件。
- 前向查找:(?<=pattern)表示匹配pattern前面的字符串,但不包括pattern本身
- 前向否定查找:(?<!pattern)表示匹配不在pattern前面的字符串
- 后向查找:(?=pattern)表示匹配pattern后面的字符串,但不包括pattern本身
- 后向否定查找:(?!pattern)表示匹配不在pattern后面的字符串
例如,以下代码可以通过前向否定查找和后向否定查找来匹配一个字符串中除了特定字符串外的所有字符:
import re
text = "hello world, this is a test"
pattern = "(?<!test).(?<!this).(?<!world),(?!test)(?!this)(?!world).*(?<!test).(?<!this).(?<!world)"
result = re.findall(pattern, text)
print(result) # [" ", "a", " ", "t", "e", "s", "t"]
三、优秀实践
- 提前编译正则表达式
在进行大量正则表达式匹配的时候,可以考虑将正则表达式编译为一个re.Pattern对象,这样可以避免重复编译造成的性能损失。例如,以下代码将一个正则表达式编译为一个re.Pattern对象:
import re
pattern = re.compile("\d+")
result = pattern.findall("hello 123 world 456")
- 合理使用正则表达式
在使用正则表达式的时候,要根据具体的问题来选择合适的表达式,避免表达式过于复杂,导致性能下降或匹配出的结果不准确。同时,可以使用一些工具来辅助编写正则表达式,例如Online Regex Tester、RegexBuddy等。
- 小心特殊字符转义
在使用正则表达式的时候,要注意对特殊字符进行转义,例如".“、”*“、”+“等。同时,要注意Python中的字符串转义字符与正则表达式中的转义字符的差异,正确地使用转义字符可以避免匹配出错误的结果。例如,以下代码会匹配到”😕/example.com",而不是"http://example.com",因为"."被解释为任意字符:
import re
text = "http://example.com"
pattern = "http://.*\.com"
result = re.findall(pattern, text)
print(result) # ["://example.com"]
正确的写法应该将".“转义为”.",例如:
import re
text = "http://example.com"
pattern = "http://.*\\.com"
result = re.findall(pattern, text)
print(result) # ["http://example.com"]
参考资料:
- Python re模块官方文档:https://docs.python.org/zh-cn/3/library/re.html
- Python正则表达式教程:https://www.runoob.com/regexp/regexp-syntax.html
- 正则表达式30分钟入门教程:https://deerchao.cn/tutorials/regex/regex.htm
- 实用的正则表达式收集:https://regex101.com/
- Python Regular Expressions Cheat Sheet:https://www.debuggex.com/cheatsheet/regex/python