正则表达式(Python)

编程的时候经常需要处理字符串,大部分时候基本的字符串处理函数就可以解决问题。但遇到一些稍复杂的任务,要处理的字符串不是特定的,而是有一定的模式或规则的,就可以考虑使用正则匹配。把最近学的正则表达式知识粗浅的总结一下,欢迎指正。

正则表达式

正则表达式验证网站:https://regexr-cn.com

后面的示例都需要提前导入 re 模块:

import re 

正则表达式常用于如下场景。

  • 查找:从大量信息中快速提取指定内容。
  • 替换:将指定格式的文本进行正则匹配查找,找到之后进行特定替换。
  • 验证:表单提交时,进行用户名密码的验证。

先看几个例子:

# 导入模块
import re 

# 搜索你想要的内容,并取出来
ret = re.search(r'\d{4}', '从1988到2022,从2023到2050') 
print(ret.group())	# 1988
# 获取多个
ret = re.findall(r'从\d{4}', '从1988到2022,从2023到2050')
print(ret) 		# ['从1988', '从2023']
# 用()提取局部值
ret = re.findall(r'从(\d{4})', '从1988到2022,从2023到2050')
print(ret) 		# ['1988', '2023']

# 判断字符串是否包含你想要的内容
ret = re.search(r'(error|failure)', 'System log: Fatal error!') 
print(ret.group())     # error

# 替换你想替换的内容
ret = re.sub(r'(blue|red)', 'nice','blue socks and red shoes')
print(ret)	# nice socks and nice shoes
表达式

基本的正则表达式包含如下要素:(1)字符类(2)数量限定符(3)位置限定符(4)特殊符号。

(1)字符类

代码说明举例
.匹配一个除换行(“\n”和"\r")外的任何字符。要匹配.本身,要加转义符\abc. 可以匹配 abc6 或 abcd
[]匹配括号中的任意一个字符[abc]d 可以匹配 ad,bd,cd;[0-9] 可以匹配 0,1,2,…,9
-在[]内表示字符范围内的任意一个字符[0-9a-fA-F] 可以匹配一位16进制数字
^在[]内表示除括号内字符的其他任意一个字符(在句子的开头表示匹配开始位置)[^xy]1 不能匹配x1,y1,可以匹配 a1,b1等
\w匹配字母或数字或下划线或汉字
\W匹配一个 非 字母数字下划线或汉字
\s匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S匹配一个 非 不可见字符,即匹配一个可见字符。等价于 [^\f\n\r\t\v]。
\d匹配一个数字字符,等价于[0-9]。
\D匹配一个 非 数字字符。等价于[^0-9]

(2)数量限定符

语法说明举例
*重复零次或更多次[0-9][0-9]* 匹配至少一位数字
+重复一次或更多次[0-9]+匹配至少一位数字
?重复零次或一次,前一个字符出现或不出现ax?匹配 a 或 ax
{n}重复n次[1-9][0-9]{2},匹配 100 到 999 的整数
{n,}重复n次或更多次[1-9][0-9]{2,},匹配 100 及以上的整数
{n,m}重复n到m次[1-9][0-9]{1,2},匹配 10 到 999 之间的整数
{,m}最多重复m次[1-9][0-9]{,2},匹配 1 到 999 之间的整数

(3)位置限定符

语法说明举例
^匹配整个字符串(句子)的开始(在字符类 “[]” 里表示非(不匹配)的意思)
$匹配整个字符串(句子)的结束^\d\d\d$ 匹配三个全部都为数字的字符串,“123”
\<匹配单词开头\<th 匹配 this,但不匹配 ethernet,tenth
\>匹配单词结尾p\> 匹配 leap,但不匹配 parent,sleepy
\<\>匹配词(word)的开始(\<)和结束(\>)。\<the\>匹配"for the wise"中的"the",但不能匹配"otherwise"中的"the"
\b匹配一个边界(单词+空格或换行符)。用于字符串开头或结尾er\b 匹配 never 中的 er,但不能匹配 verb 中的 er。
\B匹配 非 单词开头或结尾位置。匹配非单词边界。er\B能匹配 verb 中的 er,但不能匹配 never 中的 er。

(4)特殊字符

语法说明举例
\转义字符。将普通字符和特殊字符之间进行互转。‘\.’ 想匹配 . 这个特殊字符,需要转义。
()将一部分括起来组成一个单元,对单元使用数量限定符([0-9]{1,3}\.){3}[0-9]{1,3} 匹配 IPv4 地址。最后一个数字后面没有.
|两个子表达式之间表示或的关系n(o|an) 匹配 no 或 nan

(5)懒惰匹配

当限定符后紧跟一个 ‘?’ ,表示懒惰匹配

语法说明举例
*?重复任意次,但尽可能少重复如下示例
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复
# a.*b 表示以 a 开头,中间尽量多的字符,以 b 结尾
ret = re.search('a.*b','aaaabbbb')
print(ret.group()) # aaaabbbb

# a.*?b 表示以 a 开头,中间尽量少的字符,以 b 结尾
ret = re.search('a.*?b','aaaabbbb')
print(ret.group()) # aaaab
分组
语法作用举例
(表达式)搜索时匹配一个分组如下示例
(表达式1|表达式2)分组内多个表达式之间,取或如下示例
(?:表达式)搜索时匹配,但不计入分组如下示例
(?P<name>表达式)分组别名。group时可以根据别名取数如下示例
(?=表达式)前向(右)肯定断言如下示例
(?!表达式)前向否定断言
(?<=表达式)后向(左)肯定断言如下示例
(?<!表达式)后向否定断言如下示例

分组

(表达式)

使用()实现分组机制,除了获得整个匹配,还能在匹配中选择每一个分组。

import re

html = '''
</div>
    <div class="small_wrap j_small_wrap">
        <a rel="noreferrer"  href="#" οnclick="return false;" class="small_btn_pre j_small_pic_pre" style="display:none"></a>
        <a rel="noreferrer"  href="#" οnclick="return false;" class="small_btn_next j_small_pic_next" style="display:none"></a>
        <div class="small_list j_small_list cleafix"></div>
        <div class="small_list_gallery"></div>   
    </div>                   
</div>
'''

# 添加 ”()“,增加分组功能,匹配到整个字符串后,仅提取括号内目标值
res = re.findall('<div class="(.*?)">', html)
print(res)	#['small_wrap j_small_wrap', 'small_list j_small_list cleafix', 'small_list_gallery']

# 如果去掉 ”()“,提取整个匹配字符串
res = re.findall('<div class=".*?">', html)
print(res)	# ['<div class="small_wrap j_small_wrap">', '<div class="small_list j_small_list cleafix">', '<div class="small_list_gallery">']

分组内的或表达式

(表达式1 | 表达式2 | 表达式3)

使用()实现分组机制时可以使用 | 关系

import re

# 提取文件后缀
res = re.findall('(\.png|\.mpeg|\.bmp)', "pic.bmp and pic1.png")
print(res) # ['.bmp', '.png']
# 提取文件名和文件后缀
res = re.findall('(\w+)\.(png|mpeg|bmp)', "pic.bmp and pic1.png")
print(res) # [('pic', 'bmp'), ('pic1', 'png')]

非捕获分组

(?:表达式)

使用()实现分组机制,但只想取部分括号里的数据。

import re

res = re.findall('(?:\w*)-(\d*)', "abcd-12, asw-345")
print(res) # ['12', '345']

res = re.findall('(\w*)-(\d*)', "abcd-12, asw-345")
print(res) # [('abcd', '12'), ('asw', '345')]

分组取别名

(?P<name>表达式)

为分组取别名,方便引用

import re

sentence = 'cats are fast'
regex = re.compile('(?P<animal>\w+) (?P<verb>\w+) (?P<adjective>\w+)')
matched = re.search(regex, sentence)
print(matched.groupdict()) #{'animal': 'cats', 'verb': 'are', 'adjective': 'fast'}
print(matched.group('adjective')) # fast
print(matched.group(0)) #cats are fast
print(matched.group(1)) # cats
print(matched.group(2)) # are
print(matched.group(3)) # fast
print(matched.group(4)) # 错误 no such group
断言

(?=表达式)

往前面的文字(向右)看是否匹配括号里的内容,但实际不获取,只做比较

import re

string = "I'm singing while you're dancing."
# \b\w+(?=ing\b),表示匹配以 ing 结尾的单词的前面的部分(除ing以外的部分)。
ret = re.findall(r'\b\w+(?=ing\b)', string) 
print(ret) # ['sing', 'danc']

(?<=表达式)

往后面的文字(向左)看是否匹配括号里的内容,但实际不获取,只做比较

import re

string = "ID:1234, Graduate:2014, Birth:1988"
# (?<=Birth):(\d{4}),表示匹配前面为 Birth 的 : 之后的4个数字
ret = re.search(r'(?<=Birth):(\d{4})', string) 
print(ret.group(1)) # 1988

Python 函数

下面列举下 Python re 模块中常用的几个正则函数:

compile()

re.compile (pattern, flags=0)

把正则表达式语法转化成正则表达式对象,返回一个 re.Pattern 类型的值,供 match()search() 这两个函数使用(其实这些函数也可以直接使用字符串)。

pattern:一个字符串形式的正则表达式
flags:可选,表示匹配的模式,模式如下
re.I:忽略大小写
re.L:表特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.M:多行模式

string_pattern = re.compile(r'\d{4}')
re.search(string_pattern, '从1988到2022')
或者
re.search(r'\d{4}', '从1988到2022')
search()

re.search (pattern, string, flags=0)

扫描整个字符串来查找匹配,一旦找到第一个匹配对象就停止工作,返回值为 match 对象(使用 match.group() 提取匹配字符),没找到返回None

year_pattern = re.compile(r'\d{4}') 
string1 = '从1988到2022' 
match2 = re.search(year_pattern, string1) 
print(match2.group())     # 1988
match()

re.match (pattern, string, flags=0)

从字符串开头的第一个字符开始匹配,也就是只报告从位置 0 开始的匹配情况。如果找到返回match对象(使用match.group()提取匹配字符),没找到返回None。

year_pattern = re.compile(r'\d{4}') 
string1 = '从1988到2022'
match1 = re.match(year_pattern, string1)         
print(match1) 		# None

match() 和 search() 都只返回一个匹配对象。findall() 会返回多个匹配对象。

findall()

pattern.findall (string)
re.findall (pattern,string)

匹配到全部以列表返回,返回值为字符串数组,失败返回None

string = '从1988到2022' 
string_pattern = re.compile(r'\d{4}') 
res = string_pattern.findall(string) 
print(res)  # ['1998', '2022']
string = '从1988到2022'
string_pattern = re.compile(r'\d{4}') 
res = re.findall(string_pattern, string)
print(res) # ['1998', '2022']
split()

re.split (pattern, string, maxsplit=0, flags=0)

按照匹配的字符串进行分割

string = '1cat2dog3pig4' 
res = re.split(r'\d+', string) 
print(res)  #['', 'cat', 'dog', 'pig', '']
sub()

re.sub (pattern, repl, string, count=0, flags=0)

正则的替换,返回替换之后的字符串。3个必选参数,2个可选参数。

pattern,表示正则中的模式字符串
repl,用来替换的字符串
string,要被处理,要被替换的字符串
count,替换次数,默认0是全部替换
flags,

p = re.compile('(blue|red)')
print(p.sub('nice','blue socks and red shoes’)) # nice socks and nice shoes
print(p.sub('nice','blue socks and red shoes’, count=1)) # nice socks and red shoes
# 把数字替换成字符串
st = "hello 2022"
st = re.sub("([0-9]+)","panda",st)
print(st) # hello panda
# 把连续2个a替换成1个a
st = "hello aabbaa"
st = re.sub("(a{2})","a",st)
print(st) # hello abba
flags
语法描述举例
re.I不区分大小写
re.L做本地化识别(locate-aware)匹配
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行符在内的所有字符
re.U根据 Unicode 解析字符,影响 \w, \W, \b, \B.
# 忽略大小写
res = re.search('[a-z]+', 'aSdf\dx', flags=re.I)
print(res.group())  # 结果为 aSdf,如果去掉 re.I,则返回 a。
# 多行模式,其中\n是换行符
res = re.search('^df', '\ngqwqw\ndfas\nadf\nasdf', flags=re.M)
print(res.group())  # 结果为 df,如果去掉 re.M,则返回值为 None。
# 匹配任意字符
res = re.search('.', '\ngqwqw\ndfas\nadf\nasdf', flags=re.S)
print(res.group())  # 结果为 “换行符\n”,也就是一个空白行。如果去掉 re.S,则匹配到 g 。

常用正则表达式

只能输入数字:"^[0-9]*$"。

只能输入n位的数字:"^\d{n}$"。

只能输入至少n位的数字:"^\d{n,}$"。

只能输入m~n位的数字:。"^\d{m,n}$"

只能输入零或非零开头的数字:"^(0|[1-9][0-9]*)$"。

只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。

只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。

只能输入非零的正整数:"^\+?[1-9][0-9]*$"。

只能输入非零的负整数:"^\-[1-9][0-9]*$"。

只能输入长度为3的字符:"^.{3}$"。

只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。

只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。

只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。

只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。

验证用户密码:"^[a-zA-Z]"w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。

只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"

验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。

验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。

验证电话号码:"^(\d{3,4}-)?\d{7,8}$"正确格式为:“XXX-XXXXXXX”、“XXXX- XXXXXXXX”、“XXX-XXXXXXX”、“XXX-XXXXXXXX”、“XXXXXXX” 和 “XXXXXXXX”。

验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。

参考:

  1. 正则表达式全解析+常用示例
  2. Python正则表达式,这一篇就够了!
  3. 最全常用正则表达式大全
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值