导读:
正则在各语言中的使用是有差异的,本文以 Python 3 为基础。
本文主要讲述的是正则的语法,对于 re 模块不做过多描述,只会对一些特殊地方做提示。
很多人觉得正则很难,在我看来,这些人一定是没有用心。
其实正则很简单,根据二八原则,我们只需要懂 20% 的内容就可以解决 80% 的问题了。
我曾经有几年几乎每天都跟正则打交道,刚接手项目的时候我对正则也是一无所知,花半小时百度了一下,然后写了几个 demo,就开始正式接手了。
三年多时间,我用到的正则鲜有超出我最初半小时百度到的知识的。
1.1、基础语法
s = '123abc你好' re.search('\d+' , s).group () re.search('\w+' , s).group ()
1.2、修饰符
修饰符
A
使
\w
只匹配 ASCII 字符,
\W
匹配非 ASCII 字符。
s = '123abc你好' re.search('\w+' , s, re.A).group () re.search('\W+' , s, re.A).group ()
但是描述中还有
\d
和
\D
,数字不都是 ASCII 字符吗?
这是什么意思?
别忘了,还有 全角和半角!
s = '0123456789'
# 全角数字 re.search('\d+' , s, re.U).group ()
多行匹配的模式其实也不常用,很少有一行行规整的数据。
s = 'aaa\r\nbbb\r\nccc' re.findall('^[\s\w]*?$' , s) re.findall('^[\s\w]*?$' , s, re.M)
['aaa\r\nbbb\r\nccc' ] ['aaa\r' , 'bbb\r' , 'ccc' ]
s = 'aaa\r\nbbb\r\nccc' re.findall('^.*' , s) re.findall('^.*' , s, re.S)
['aaa\r'] ['aaa\r\nbbb\r\nccc']
rc = re.compile(r""" \d+ # 匹配数字 # 和字母 [a-zA-Z]+ """ , re.X) rc.search('123abc' ).group()
注意,用了
X
修饰符后,正则中的所有空格会被忽略,包括正则里面的原本有用的空格。
如果正则中有需要使用空格,只能用
\s
代替。
修饰符不仅可以代码中指定,也可以在正则中指定。
(?aiLmsux)
表示了以上所有的修饰符,具体用的时候需要哪个就在 ? 后面加上对应的字母,示例如下,
(?a)
和
re.A
效果是一样的:
s = '123abc你好' re.search('(?a)\w+'
, s).group () re.search('\w+' , s, re.A).group ()
1.3、贪婪与懒惰
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。
s = 'aabab' re.search('a.*b' , s).group () # 这就是贪婪 re.search('a.*?b' , s).group () # 这就是懒惰
*?
、
+?
、
{n,}?
这些表达式就是懒惰(在贪婪的基础上加上
?
)。
2.1、捕获分组
注意:
在其他语言或者网上的一些正则工具中,分组命名的语法是
(?
exp)
或
(?'name'exp)
,但在 Python 里,这样写会报错:
This named group syntax is not supported in this regex dialect。
Python 中正确的写法是:
(?P
exp)
s = '姓名:张三;性别:男;电话:138123456789' m = re.search('姓名[:: ](\w+ ).*?电话[:: ](\d{11} )', s) if m: name = m.group(1) phone = m.group(2) print(f'name:{name}, phone:{phone}')
name :张三, phone :13812345678
(?P
exp)
有时还是会用到的,
(?P=name)
则很少情况下会用到。
我想了一个
(?P=name)
的使用示例,给大家看下效果:
s = '''张三 30 138123456789 ''' pattern = r'.*?)>(.*?)(?P=name)>' It = re.findall(pattern, s)
[('name', '张三'), ('age', '30 '), ('phone', '138123456789 ')]
2.2、零宽断言
注意:
正则中常用的前项界定
(?<=exp)
和前项否定界定
(? 在 Python 中可能会报错:
look-behind requires fixed-width pattern,原因是 python 中 前项界定的表达式必须是定长的,看如下示例:
(?<=aaa) (?<=aaa|bbb) (?<=aaa|bb) (?<=\d+) (?<=\d{3})