Python 学习笔记 正则表达式

本文聚焦Python中正则表达式的使用。介绍了正则表达式的特殊符号和字符(元字符),如各种分组符号及其作用、拓展符号等。还阐述了正则表达式与Python的结合,包括re模块的编译、匹配对象方法,以及findall、sub等方法的使用,同时提醒了使用原始字符串避免冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

特殊符号和字符(元字符)

表示法描述正则表达式示例
符号
literal匹配文本字符串的字面值foo
re1|re2匹配正则表达式re1或者re2foo|bar
.匹配任何字符(除\n之外)b.b
^匹配字符串起始部分
$匹配字符串终止部分
*匹配0次或多次前面出现的正则表达式
+匹配1次或多次前面出现的正则表达式
?匹配0次或1次前面出现的正则表达式
{N}匹配N次前面出现的正则表达式
{M,N}匹配M-N次前面出现的正则表达式
[…]匹配来自字符集的任意单一字符
[…x-y…]匹配x~y范围中的任意单一字符
[^…]不匹配来自字符集的任何一个字符,或某一范围的字符
(*|+|?|{})?用于匹配上面频繁出现/重复出现符号的非贪婪版本(*,+,?,{})
(…)匹配封闭的正则表达式,然后另存为子组
特殊字符
\d匹配任何十进制数字,与[0-9]一致(\D与\d相反,匹配任何非十进制数,与[^0-9]一样)
\w匹配任何字母数字字符(\W与之相反)
\s匹配任何空格字符,与[\n\t\r\v\f]一致,(\S与之相反)
\b匹配任何单词边界(\B与之相反)
\N匹配已保存的数组N
\c逐字匹配任何特殊字符c(即按字面匹配,不转义了)
\A(\Z)匹配字符串的起始(结束)(与^和$一致)
拓展表示法
(?iLmsux)在正则表达式中嵌入一个或多个特殊“标记”参数(就是下面re中那个模块属性)(或者通过函数/方法)
(?:…)表示一个匹配不用保存的分组
(?P<name>…)
(?P=name)
(?#…)表示注释
(?=…)正向前视断言
(?!..)负向前视断言
(?<=…)正向后视断言
(?<!..)负向前视断言
(?(id/name)Y|N)如果某匹配组存在,就与Y匹配,否则与x匹配

使用圆括号()指定分组
()作用:
①对正则表达式进行分组
②匹配子组

分组好处:
当有两个不同的正则表达式而且想用他们来比较同一字符串
分组可以对整个分组使用重复操作符。

副作用:
匹配模式的子字符串可以保存起来供后续使用


拓展符号:

1.(?iLmsux)在正则表达式中指定特殊标记

①标记——re.I/re.IHNORECESE

>>> import re
>>> re.findall('(?i)yes','yes?Yes! YES!!!')#相当于使用了re.I
['yes', 'Yes', 'YES']

②标记——re.M/re.MULTILINE,可匹配多行

>>> re.findall('(?im)(^th[\w ]+)',"""
This line is the first,
another line,
that line,it's the best
	""")
['This line is the first', 'that line']

③标记——re.S/re.DOTALL,点号(.)能匹配任何字符,包括\n

④标记——re.X/re.VERBOSE,允许用户通过抑制在正则表达式中使用空白符(除了在字符类或者反斜线转义中)来创建更易读的正则表达式,此外,散列,注释和井号也可用于一个注释的开始,只要他们不在一个用反斜线转义的字符类中

>>> re.search(r'''(?x)
\((\d{3})\) #区号
[ ]         #空白符
(\d{3})     #前缀
-           #横线
(\d{4})     #终点数字
''','(800) 555-1212').groups()
('800', '555', '1212')

2.(?:…)

对部分正则表达式进行分组,但是不会保存该分组.


3.(?P<name>) , (?P=name)

(?P<name>) 使用一个名称标识符(而不是默认的1,2,3,…,N)来保存匹配分组,

使用默认数字来标识分组时,通过\1 , \2 , \3,…\N来检索。
而使用名称标识符时,用(\g<name>)来检索。

>>> re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})','(\g<areacode>) \g<prefix>-xxxx','(800) 555-1212')
'(800) 555-xxxx'

!!!
(?P=name)直接使用前者(?P<name>) 的模式而不用重新写相同的正则表达式

>>> bool(re.match(r'''(?x)

#match(800) 555-1212 ,save areacode,prefix,no.
\((?P<areacode>\d{3})\)[ ](?P<prefix>\d{3})-(?P<number>\d{4})

#space
[ ]

#match 800-555-1212
(?P=areacode)-(?P=prefix)-(?P=number)

#space
[ ]

#match 18005551212
1(?P=areacode)(?P=prefix)(?P=number)

''','(800) 555-1212 800-555-1212 18005551212'))
True
4.(?=…), (?!…)
5.(?(id/name)Y|X)

二,正则表达式与Python

1.re模块
函数/方法描述
仅是re模块函数
compile(pattern,flags=0)
re模块函数和正则表达式对象的方法
match(pattern,string,flags=0)
search(pattern,string,flags=0)
findall(pattern,string[,flags])查询字符串中的某个正则表达式模式全部的非重复出现情况。返回一个列表。
finditer(pattern,string[,flags])返回迭代器,对于每一次匹配迭代器都返回一个匹配对象
splitl(pattern,string,max=0)
re模块函数和正则表达式对象方法
sub(pattern,repl,string,count=0)
purge()
常用的匹配对象方法
group(num=0)
groups(default=None)
groupdict(default=None)
常用的模块属性
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通过反斜线转义,否则所有空格加上#(以及在该行中所有的后续文字)都被忽略,除非在一个字符类中或者允许注释并提高可读性

2.

编译正则表达式:
在模式匹配发生前,正则表达式模式必须编译成正则表达式对象。
由于其被多次使用,强烈建议使用预编译

①complie函数
一些特殊的正则表达式编译,可选的标记可能以参数的形式给出,这些标记允许不区分大小写的匹配,使用系统的本地化设置来匹配字母数字等,它们可以通过安慰或操作符(|)合并。

若想在方法中使用这些标记,它们必须已经集成到已编译的正则表达式对象中,或使用直接嵌入到正则表达式本身的(?F)标记,其中F是一个或多个i,m,s,同时使用时(?im)不要用|,其实就是拓展符号中的(?iLmsux)


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

成功调用match()或search()后返回匹配对象。匹配对象的两种方法group() , groups()

group()返回整个匹配对象或特定子组
group(num=0)

groups()仅返回一个包含全部匹配子组的元组。
groups(default=None)


③使用match()方法匹配字符串

试图从字符串的起始部分对模式进行匹配。
匹配成功,返回匹配对象
匹配失败,返回None

>>> import re
>>> m=re.match('foo','food on the table')
>>> if m is not None:
	m.group()#不用if,若匹配失败,会出现AttributeError异常

	
'foo'
>>> m
<re.Match object; span=(0, 3), match='foo'>

④使用search()在一个字符串中查找模式

使用match

>>> m=re.match('foo','seafood')
>>> if m is not None:m.group()

>>> #匹配失败

使用search:

>>> re.search('foo','seafood').group()
'foo'

!!!match与search都可使用可选的标记参数。
等价的正则表达式方法还可以使用可选的pos和endpos参数赖志定目标字符串的搜索范围。


3.分组与其他符号

分组

>>> m=re.match('(a)(b)','ab')
>>> m.group()
'ab'
>>> m.group(1)
'a'
>>> m.group(2)
'b'
>>> m.groups()
('a', 'b')
>>> m=re.match('(a(b))','ab')
>>> m.group()
'ab'
>>> m.group(1)
'ab'
>>> m.group(2)
'b'
>>> m.groups()
('ab', 'b')

还可使用\N(N为分组编号)使用分组

>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|d{4})',r'\2/\1/\3','2/20/991')
'20/2/991'

边界

>>> m=re.search(r'\bthe','bite the dog')
>>> if m is not None:
	m.group()

	
'the'
>>> m=re.search(r'\bthe','bitethe dog')
>>> if m is not None:
	m.group()

	#查找(匹配)失败
>>> m=re.search(r'\Bthe','bitethe dog')
>>> if m is not None:
	m.group()

	
'the'

4.findall与finditer方法

使用findall()和finditer()查找每一次出现的位置

findall()查询字符串中的某个正则表达式模式全部的非重复出现情况。返回一个列表。
(如果没找到,则返回空列表)

>>> re.findall('car','carry the barcardi to the car')
['car', 'car', 'car']
>>> re.findall(r'(car).{2,7}(the)','carry the barcardi to the car')
[('car', 'the'), ('car', 'the')]

finditer(),返回迭代器,对于每一次匹配迭代器都返回一个匹配对象。
注意Python3中迭代器用方法__next__()

>>> re.finditer(r'(th\w+) and (th\w+)','This and that',re.I).__next__().group()
'This and that'

!!!match与search都可使用可选的标记参数。
等价的正则表达式方法还可以使用可选的pos和endpos参数赖志定目标字符串的搜索范围。


5.sub()和subn()搜索与替换

将字符串中所有匹配正则表达式的部分进行某种形式的替换。

返回替换后的字符串

subn比之sub多返回一个替换数目,以元组形式——(字符串,n)

>>> re.sub('[ae]','x','abcdef')
'xbcdxf'
>>> re.subn('[ae]','x','abcdef')
('xbcdxf', 2)

还可使用\N(N为分组编号)使用分组

>>> re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|d{4})',r'\2/\1/\3','2/20/991')
'20/2/991'

6.在限定模式上使用split()分割字符串
>>> import re
>>> DATA =(
	'Mountain View, CA 94040',
	'Sunnyvale, CA',
	'Los Altos, 94026',
	'Cupertino 95014',
	'Palo Alto CA',
	)
>>> for datum in DATA:
	print(re.split(', |(?= (?:\d{5}|[A-Z]{2}))',datum))

	
['Mountain View', 'CA', ' 94040']
['Sunnyvale', 'CA']
['Los Altos', '94026']
['Cupertino', ' 95014']
['Palo Alto', ' CA']
7.杂项

\w 和 \W 同时受 re.L/re.LOCALE 和 Unicode(re.U/re.UNICODE) 影响

!!!尽量使用 Python原始字符串

因为ASCLL和正则表达式特殊字符之间存在冲突。

比如\b在ASCLL码中标识退格 ,正则表达式中表示单词边界,
需要“\b”

建议使用原始字符串r“…”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值