正则表达式 -- 模式匹配

匹配单个字符
字符 功能
. 匹配任意1个字符(除了\n)
[ ] 匹配[ ]中列举的字符
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即 空格,tab键
\S 匹配非空白
\w 匹配单词字符,即a-z、A-Z、0-9、_
\W 匹配非单词字符
  • 实例演示: .
import re

ret = re.match(".", "M")
print(ret.group())

ret = re.match("t.o", "too")
print(ret.group())

ret = re.match("t.o", "two")
print(ret.group())
M
too
two
  • 实例演示:[ ]
import re

# 大小写h都可以的情况
ret = re.match("[hH]", "hello Python")
print(ret.group())
ret = re.match("[hH]ello Python", "Hello Python")
print(ret.group())

# 匹配0到9第一种写法
ret = re.match("[0123456789]Hello Python", "7Hello Python")
print(ret.group())

# 匹配0到9第二种写法
ret = re.match("[0-9]Hello Python", "7Hello Python")
print(ret.group())

ret = re.match("[0-35-9]Hello Python", "7Hello Python")
print(ret.group())

# 下面这个正则不能够匹配到数字4,因此ret为None
ret = re.match("[0-35-9]Hello Python", "4Hello Python")
# print(ret.group())
h
Hello Python
7Hello Python
7Hello Python
7Hello Python
None
  • 实例演示:\d
import re

ret = re.match("嫦娥\d号", "嫦娥1号发射成功")
print(ret.group())

ret = re.match("嫦娥\d号", "嫦娥2号发射成功")
print(ret.group())

ret = re.match("嫦娥\d号", "嫦娥3号发射成功")
print(ret.group())
嫦娥1号
嫦娥2号
嫦娥3号
匹配多个字符
字符 功能
* 匹配前一个字符出现0次或者n次,即可有可无
+ 匹配前一个字符出现1次或者n次,即至少有1次
? 匹配前一个字符出现1次或者0次,即要么有要么没有
{m} 匹配前一个字符出现m次
{m,n} 匹配前一个字符出现从m到n次
  • 实例演示:*
    匹配一个字符串,首字母大写,后面没有字符、或有小写字母
import re

ret = re.match("[A-Z][a-z]*","M")
print(ret.group())

ret = re.match("[A-Z][a-z]*","MnnM")
print(ret.group())

ret = re.match("[A-Z][a-z]*","Aabcdef")
print(ret.group())
M
Mnn
Aabcdef
  • 实例演示:+
    匹配变量名是否有效
import re

names = ["name1", "_name", "2_name", "__name__"]

for name in names:
    ret = re.match("[a-zA-Z_]+[\w]*", name)
    if ret:
        print("变量名 %s 符合要求" % ret.group())
    else:
        print("变量名 %s 非法" % name)
变量名 name1 符合要求
变量名 _name 符合要求
变量名 2_name 非法
变量名 __name__ 符合要求
  • 实例演示:?
    匹配出0到99之间的数字
    由于match函数默认情况下,只要匹配到符合规则的字符串之后,就返回结果,所以当符合规则的字符串后有非法字符时,无法得到正确结果,需要使用$来限制结尾字符
import re

ret = re.match("[1-9]?[0-9]", "7")
print(ret.group())

ret = re.match("[1-9]?\d", "33")
print(ret.group())

ret = re.match("[1-9]?\d", "09")
print(ret.group())
7
33
0  # 这个结果并不是想要的,利用$才能解决
  • 实例演示:{m}{m, n}
    匹配出,8到20位的密码,可以是大小写英文字母、数字、下划线
import re

ret = re.match("[a-zA-Z0-9_]{6}","12a3g45678")
print(ret.group())

ret = re.match("[a-zA-Z0-9_]{8,20}","1ad12f23s34455ff66")
print(ret.group())
12a3g4
1ad12f23s34455ff66
  • 练习:
    匹配出163的邮箱地址,且@符号之前有4到20位,如:neuedu@163.com
i = ['neuedu@163.com', '123neu@163.com', 
     'neuedu@aa@163.com', 'neuedu@126.com', 
     'neuedu@163acom']

for s in i:
    if re.match(r'[\w]{4,20}@163\.com', s) is None:
        print('%s:格式错误' % s)
    else:
        print('%s:格式正确' % s)
匹配开头结尾
字符 功能
^ 匹配字符串开头
$ 匹配字符串结尾
  • 修正之前的错误
import re

# 不正确的情况
ret = re.match("[1-9]?\d", "09")
print(ret.group())  # 0

# 修正之后的
ret = re.match("[1-9]?\d$", "09")
if ret:
    print(ret.group())
else:
    print("不在0-99之间")
  • 实例演示: $
import re

email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]

for email in email_list:
    ret = re.match("[\w]{4,20}@163\.com", email)
    if ret:
        print("%s 是符合规定的邮件地址,匹配后的结果是:%s" % (email, ret.group()))
    else:
        print("%s 不符合要求" % email)
xiaoWang@163.com 是符合规定的邮件地址,匹配后的结果是:xiaoWang@163.com
xiaoWang@163.comheihei 是符合规定的邮件地址,匹配后的结果是:xiaoWang@163.com
.com.xiaowang@qq.com 不符合要求

第2个地址被错误的当成了合法地址,通过添加结尾字符来修正

ret = re.match("[\w]{4,20}@163\.com$", email)
匹配分组
字符 功能
(规则) 将规则定义为一个分组
(规则1 | 规则2 ...) 从多个规则中选择一个规则进行匹配
\组号 使用指定的分组进行匹配
(?P<别名> reg ) 为规则分组起一个别名
(?P=别名) 使用别名引用分组进行匹配
  • 实例演示:|
    匹配出0-100之间的数字(注意 1位数、2位数表示形式的不同)
import re

ret = re.match("[1-9]?\d$|100", "8")
print(ret.group()) 

ret = re.match("[1-9]?\d$|100", "78")
print(ret.group())  

ret = re.match("[1-9]?\d$|100", "100")
print(ret.group())  
8
78
100
  • 实例演示:()
    匹配出163、126、qq邮箱
import re

ret = re.match("\w{4,20}@163\.com", "test@163.com")
print(ret.group())  # test@163.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@126.com")
print(ret.group())  # test@126.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@qq.com")
print(ret.group())  # test@qq.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@gmail.com")
if ret:
    print(ret.group())
else:
    print("不是163、126、qq邮箱")  # 不是163、126、qq邮箱
test@163.com
test@126.com
test@qq.com
不是163、126、qq邮箱
  • 匹配固定电话号码
print(re.match('0[1-9]?\d{1,2}-[1-9][0-9]{6,7}', '024-12345678'))
<_sre.SRE_Match object; span=(0, 12), match='024-12345678'>
  • 提取区号和电话号码
>>> import re
>>> ret = re.match("([^-]*)-(\d+)","010-12345678")
>>> ret.group()
'010-12345678'
>>> ret.group(1)
'010'
>>> ret.group(2)
'12345678'
  • 课堂练习:匹配不是以4、7结尾的手机号码(11位)
import re

tels = ["13100001234", "18912344321", "10086", "18800007777"]

for tel in tels:
    ret = re.match("1\d{9}[0-35-68-9]$", tel)
    if ret:
        print(ret.group())
    else:
        print("%s 不是想要的手机号" % tel)
13100001234 不是想要的手机号
18912344321
10086 不是想要的手机号
18800007777 不是想要的手机号
  • 实例演示:\
  • 当某规则被重复使用时,可将其放与小括内,再使用时,用\n来引用
  • [a-z][0-9]{3}这个规则使得3次,当第2次使用时,可以用\1来替换
s = 'a123--a123==a123'
r = '[a-z][0-9]{3}--[a-z][0-9]{3}==[a-z][0-9]{3}$'
r = r'([a-z][0-9]{3})--\1==\1$'
print(re.match(r, s))

匹配出<html>hh</html>

import re

ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</html>")
print(ret.group())

ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</htmlbalabala>")
print(ret.group())
<html>hh</html>
<html>hh</htmlbalabala>
  • 第2个匹配中,遇到了非正常的html格式字符串,匹配出错
  • 正确的理解思路:如果在第一对<>中是什么,按理说在后面的那对<>中就应该是什么
# 通过引用分组中匹配到的数据即可,但是要注意是元字符串,即类似 r""这种格式
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>")
print(ret.group())

# 因为2对<>中的数据不一致,所以没有匹配出来
test_label = "<html>hh</htmlbalabala>"
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", test_label)
if ret:
    print(ret.group())
else:
    print("%s 这是一对不正确的标签" % test_label)
<html>hh</html>
<html>hh</htmlbalabala> 这是一对不正确的标签
  • 字符串前面加上r表示原生字符串,因为,正则表达式里使用\作为转义字符,这就可能造成反斜杠困扰。
  • 假如你需要匹配文本中的字符\,将需要4个反斜杠\:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
  • Python中使用原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观
>>> import re
>>> print(re.match('\\\\', '\\').group())  #未使用原义字符串
\
>>> print(re.match(r'\\', '\\').group())
  • 实例演示:\number
    匹配出<html><h1>www.neuedu.com</h1></html>
import re

labels = ["<html><h1>www.neuedu.com</h1></html>",
          "<html><h1>www.neuedu.com</html></h1>"]

for label in labels:
    ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", label)
    if ret:
        print("%s 是符合要求的标签" % ret.group())
    else:
        print("%s 不符合要求" % label)
<html><h1>www.neuedu.com</h1></html> 是符合要求的标签
<html><h1>www.neuedu.com</html></h1> 不符合要求
  • 实例演示:(?P<name>) (?P=name)
    匹配出<html><h1>www.neuedu.com</h1></html>
import re

ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>",
               "<html><h1>www.neuedu.com</h1></html>")
print(ret.group())

ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>",
               "<html><h1>www.neuedu.com</html></h2>")
if ret:
    print("%s 是符合要求的标签" % ret.group())
else:
    print("不符合要求")
<html><h1>www.neuedu.com</h1></html>
不符合要求




- end -

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 正则表达式 是一个描述字符模式的对象。 JavaScript中的正则表达式用RegExp对象表示。 正则表达式的定...
    亮亮叔家的小笔笔阅读 1,317评论 0 1
  • python的re模块--细说正则表达式 可能是东半球最详细最全面的re教程,翻译自官方文档,因为官方文档写的是真...
    立而人阅读 23,026评论 4 46
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,508评论 0 5
  • Python中的正则表达式(re) import rere.match #从开始位置开始匹配,如果开头没有则无re...
    BigJeffWang阅读 7,198评论 0 99
  • 一成不变的流程:起床,锻炼,早饭,上班,好像生活中每个早上没有变化可循!!直到那天上班途中不经意的一瞥!! ...
    晨若若曦阅读 270评论 2 6