Python基础-27-正则表达式

1. re模块

1.1 re模块函数和方法

compile(pattern, flags=0)

  • re模块函数
  • 使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象

match(pattern, string, flags=0)

  • re模块函数和正则表达式对象方法
  • 尝试第一次使用带有可选标记的正则表达式的模式匹配字符串;
  • 如果匹配成功,就返回一个匹配对象;
  • 如果匹配失败,就返回None;

search(pattern, string, flags=0)

  • re模块函数和正则表达式对象方法 使用可选标记整体搜索字符串中出现的正则表达式模式;
  • 如果匹配成功,就返回一个匹配对象;
  • 如果匹配失败,就继续向后匹配;如果都没匹配成功,就返回None;

findall(pattern, string [, flags])

  • re模块函数和正则表达式对象方法
  • 查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表

finditer(pattern, string [, flags])

  • re模块函数和正则表达式对象方法
  • 与findall()函数相同,但返回的是一个迭代器;对于每一次匹配,迭代器都返回一个匹配对象;

split(pattern, string [, max])

  • re模块函数和正则表达式对象方法
  • 根据正则表达式的模式分隔符,split函数将字符串分割成列表,然后返回成功匹配的列表;
  • 分割最多操作max次,默认分割所有匹配成功的位置;

sub(pattern, repl, string, count=0) subn(pattern, repl, string, count=0)

  • re模块函数和正则表达式对象方法
  • 使用repl替换所有正则表达式的模式在字符串中出现的位置;
  • 除非定义了count,否则就替换所有出现的位置;
  • 用来替换的部分可以是一个字符串,也可以是一个返回字符串的函数;

purge()

  • re模块函数和正则表达式对象方法
  • 清除隐式编译的正则表达式模式;

group(num=0)

  • 返回整个匹配对象,或者编号为num的特定子组;

groups(default=None)

  • 返回一个包含所有匹配子组的元组;
  • 如果没有匹配成功,返回一个空元组;

groupdict(default=None)

  • 返回一个包含所有匹配的命名子组的字段,所有的子组名称作为字典的键;
  • 如果没有匹配成功,则返回一个空字典;

1.2 常用的模块属性(用于大多数正则表达式函数的标记)

属性 描述
re.I, re.IGNORECASE 不区分大小写的匹配;
re.L, re.LOCALE 根据所使用的本地语言环境通过该w,W,b,B,s,S实现匹配;
re.M, re.MULTILINE ^和$分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾;
re.S, re.DOTALL “.”点号通常匹配除了n之外的所有单个字符,该标记表示点号可以匹配全部字符;
re.X, re.VERBOSE 通过反斜杠转义,否则所有空格加上#(以及在该行中所有后续文件)都被忽略,除非在一个字符类中或者允许注释并且提高可读性;

1.3 编译正则表达式

  • 在模式匹配发生之前,正则表达式的模式必须编译成正则表达式对象。
  • 由于正则表达式在执行过程中将进行多次比较操作,因此建议使用预编译;
  • 使用compile()方法即可预编译;
  • 由于预编译会被缓存,但是无法通过api确定已编译过的正则表达式的数据,所以使用purge()函数能够清除预编译的缓存;

1.4 上面说的函数和方法

  • 几乎所有的re模块的函数,都可以作为regex对象(正则表达式对象)的方法。
  • 尽管推荐预编译,但是预编译不是必须的;
  • 如果需要编译,就使用编译过的方法;
  • 如果不需要编译,就使用函数。
  • 不管函数和方法,他们的名字就是相同的;
  • 这就函数和方法的区别:
    • 方法就是预编译后的正则表达式对象的方法;
    • 函数就是re模块提供的函数;

2. 常用例子

compile()

  • 把一个正则表达式编译成一个正则表达式对象
#!/usr/bin/env python
import  re
 
regx = re.compile("d+")
print  type(regx)#<type '_sre.SRE_Pattern'>
s = regx.search("1o23helloworld")
print s.group()

匹配对象以及group()和groups()方法

  • 当成功调用match()或者search()方法后,会返回一个对象,这个对象就是匹配对象;
  • 匹配对象可以调用group()和groups()方法;
  • group():要么返回整个匹配对象,要么返回指定子组的特定子组;
  • groups():返回包含唯一或者全部子组的元组;如果没有子组的要求,当groups()仍然返回整个匹配时,groups()返回一个空元组;

match()匹配字符串

  • 从字符串的起始位置开始匹配,当成功就返回一个匹配对象,否则就是None;
  • match()从起始位置开始匹配,当出现第一次失败后就整体失败;
#!/usr/bin/env python
import  re
 
s="1o23hel45lowo54rld"
g = re.match("d+", s )
print g.group()

search()查找字符串

  • search()会扫描整个字符串,找到第一个匹配的字符串,然后返回一个匹配对象;
  • 失败会返回None;
#!/usr/bin/env python
import  re
 
s="kk1o23hel45lowo54rld"
g = re.search("d+", s )
print g.group()

findall()查找所有匹配的字串,返回一个元组

#!/usr/bin/env python
#encoding:utf-8
import  re
r = re.findall("car","car")
print r # ['car']
 
r = re.findall("car","scary")
print r # ['car']
 
r = re.findall("car","carry the barcardi to the car")
print r # ['car', 'car', 'car']
 
r = re.findall("car","hello world")
print r # [] 空元祖

finditer()在匹配对象中迭代,返回一个元组

#!/usr/bin/env python
#encoding:utf-8
import  re
s ="this and that"
r = re.findall(r"(thw+) and (thw+)", s, re.I)# re.I 不区分大小写, 字符串前面有r,防止转义
print r # [('this', 'that')]
 
print re.finditer(r"(thw+) and (thw+)", s, re.I).next().group()# this and that
print re.finditer(r"(thw+) and (thw+)", s, re.I).next().groups()# ('this', 'that')
print re.finditer(r"(thw+) and (thw+)", s, re.I).next().group(1)# this
print re.finditer(r"(thw+) and (thw+)", s, re.I).next().group(2)# that
print[g.groups()for  g in re.finditer(r"(thw+) and (thw+)", s, re.I)]# [('this', 'that')]

重复、特殊字符以及分组

  • 分组,在正则表达式中用圆括号进行分组,这样得到的匹配结果就是有分组的;
  • 正则中有几个圆括号,就有几个分组;
#!/usr/bin/env python
#encoding:utf-8
import  re
r ="(www)-(ddd)"
m = re.match(r,"abc-123")
print m.group()# abc-123 
print m.group(1)# abc  子组1
print m.group(2)# 123   子组2
print m.groups()# ('abc', '123')  全部子组
#!/usr/bin/env python
import  re
 
m = re.match("(a(b))","ab")
print m.group()# ab
print m.group(1)# ab
print m.group(2)# b
print m.groups()# ('ab', 'b')

单个字符串中那个执行单个分组的多重匹配

#!/usr/bin/env python
#encoding:utf-8
import  re
s ="this and that"
print re.findall(r"(thw+)", s, re.I)#['this', 'that']
 
r = re.finditer(r"(thw+)", s, re.I)
g = r.next()
print g.groups()# ('this',)
print g.group(1)# this
 
g=r.next()
print g.groups()# ('that',)
print g.group(1)# that

使用sub()和subn()搜索和替换

  • sub(pattern, repl, string, count=0)
  • subn(pattern, repl, string, count=0)
  • sub()和subn()都是讲某字符中所有匹配正则表达式的部分进行某些形式的替换;
  • 用来替换的部分通常是一个字符串,也可以是一个返回字符串的函数;
  • sub()和subn()实现功能一样;
  • 但subn()还返回一个标识替换的总数;替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元祖返回
#!/usr/bin/env python
#encoding:utf-8
import  re
 
print re.sub("X","Mr. Smith","atttn: XnnDear X, n")
# atttn: Mr. Smith
# Dear Mr. Smit,
 
# 把atttn: XnnDear X, n中的X替换成Mr. Smith
print re.subn("X","Mr. Smith","atttn: XnnDear X, n")
# ('atttn: Mr. SmithnnDear Mr. Smith, n', 2) 
# 返回的是替换后的字符和替换的个数组成的元组
 
# 把atttn: XnnDear X, n中的1个X替换成Mr. Smith
print re.sub("X","Mr. Smith","atttn: XnnDear X, n",1)
# atttn: Mr. Smith
# Dear X,
 
# 把atttn: XnnDear X, n中的1个X替换成Mr. Smith
print re.subn("X","Mr. Smith","atttn: XnnDear X, n",1)
# ('atttn: Mr. SmithnnDear X, n', 1)

在限定模式上使用split()分割字符串

  • 如果分隔符不是特殊符号组成的正则表达式,re.split()与str.split()作用相同;
#!/usr/bin/env python
#encoding:utf-8
import  re
print re.split(":","hello:world:china")# ['hello', 'world', 'china'] 返回的是列表
  • 带有正则表达式的分割字符串
#!/usr/bin/env python
#encoding:utf-8
data =(
    "Mountain View, CA 94000",
    "sUNNYVALE, CA",
    "Los Altos, 99999",
    "Cupertino 98540",
    "Palo Alto CA",
)
for datum in data:
    print re.split(", |(?=(?:d{5}|[A-Z]{2}))", datum)
"""
['hello', 'world', 'china']
['Mountain View', 'CA 94000']
['sUNNYVALE', 'CA']
['Los Altos', '99999']
['Cupertino 98540']
['Palo Alto CA']

扩展符号

#!/usr/bin/env python
#encoding:utf-8
import re
print re.findall(r"(?i)yes""yes, Yes, YES")
# ['yes', 'Yes', 'YES'] 扩展标记(?i)是忽略大小写
 
print re.findall(r"th.+","The first line, the second line, the third line")
# ['the second line, the third line']
print re.findall(r"(?s)th.+","The first line, the second line, the third line")

3. 匹配单个字符

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

匹配.

#coding=utf-8

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())

匹配[ ]

#coding=utf-8

import re

# 如果hello的首字符小写,那么正则表达式需要小写的h
ret = re.match("h","hello Python"
print(ret.group())


# 如果hello的首字符大写,那么正则表达式需要大写的H
ret = re.match("H","Hello Python"
print(ret.group())

# 大小写h都可以的情况
ret = re.match("[hH]","hello Python")
print(ret.group())
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())

匹配d

#coding=utf-8

import re

# 普通的匹配方式
ret = re.match("嫦娥1号","嫦娥1号发射成功"
print(ret.group())

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

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

# 使用d进行匹配
ret = re.match("嫦娥d号","嫦娥1号发射成功"
print(ret.group())

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

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

4. 匹配多个字符

字符 功能
* 匹配前一个字符出现0次或者无限次,即可有可无
+ 匹配前一个字符出现1次或者无限次,即至少有1次
? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
{m} 匹配前一个字符出现m次
{m,n} 匹配前一个字符出现从m到n次

匹配*

#coding=utf-8
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())

匹配+

#coding=utf-8
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)

匹配?

#coding=utf-8
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())

匹配{m}

#coding=utf-8
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())

5. 匹配开头结尾

字符 功能
^ 匹配字符串开头
$ 匹配字符串结尾

匹配$

#coding=utf-8

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)

6. 匹配分组

字符 功能
竖线&#124; 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
num 引用分组num匹配到的字符串
(?P) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串

匹配|

#coding=utf-8

import re

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

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

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

# 修正之后的
ret = re.match("[1-9]?d$","08")
if ret:
    print(ret.group())
else:
    print("不在0-100之间")

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

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

ret = re.match("[1-9]?d$|100","08")
# print(ret.group())  # 不是0-100之间

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

匹配( )

#coding=utf-8

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邮箱

匹配

#coding=utf-8

import re

# 能够完成对正确的字符串的匹配
ret = re.match("<[a-zA-Z]*>w*</[a-zA-Z]*>""<html>hh</html>")
print(ret.group())

# 如果遇到非正常的html格式字符串,匹配出错
ret = re.match("<[a-zA-Z]*>w*</[a-zA-Z]*>""<html>hh</htmlbalabala>")
print(ret.group())

# 正确的理解思路:如果在第一对<>中是什么,按理说在后面的那对<>中就应该是什么

# 通过引用分组中匹配到的数据即可,但是要注意是元字符串,即类似 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)

匹配number

#coding=utf-8

import re

labels = ["<html><h1>www.itcast.cn</h1></html>""<html><h1>www.itcast.cn</h2></html>"]

for label in labels:
    ret = re.match(r"<(w*)><(w*)>.*</2></1>", label)
    if ret:
        print("%s 是符合要求的标签" % ret.group())
    else:
        print("%s 不符合要求" % label)

匹配 (?P) (?P=name)

#coding=utf-8

import re

ret = re.match(r"<(?P<name1>w*)><(?P<name2>w*)>.*</(?P=name2)></(?P=name1)>""<html><h1>www.itcast.cn</h1></html>")
ret.group()

ret = re.match(r"<(?P<name1>w*)><(?P<name2>w*)>.*</(?P=name2)></(?P=name1)>""<html><h1>www.itcast.cn</h2></html>")
ret.group()

7. 贪婪和非贪婪

  • 正则表达式的贪婪就是指尽可能多的匹配字符串;
  • 非贪婪就是尽可能少的匹配字符串;
  • 在贪婪的正则表达式后面使用?可以使其变成非贪婪;
  • Python里数量词默认是贪婪的
  • 在”*”,”?”,”+”,”{m,n}”后面加上?,使贪婪变成非贪婪

8. r的作用

>>> mm = "c:\a\b\c"
>>> mm
'c:\a\b\c'
>>> print(mm)
c:abc
>>> re.match("c:\\",mm).group()
'c:\'
>>> ret = re.match("c:\\",mm).group()
>>> print(ret)
c:
>>> ret = re.match("c:\\a",mm).group()
>>> print(ret)
c:a
>>> ret = re.match(r"c:\a",mm).group()
>>> print(ret)
c:a
>>> ret = re.match(r"c:a",mm).group()
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>


原文始发于微信公众号(Python之家):Python基础-27-正则表达式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/198455.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!