正则表达式
介绍 :在实际开发中经常会有查找某些复杂规则的字符串的需求,比如邮箱、图片地址、手机号码等,这时候想要匹配或者查找某些规则的字符串就可以使用正则表达式了。正则表达式是用于处理字符串的强大工具,其他编程语言中也有正则表达式的概念,区别只在于不同的编程语言支持的语法数量不同。 概念:正则表达式(或RE
)是一种小型的、高度专业化的编程语言,正则表达式就是记录文本规则的代码,它内嵌在Python
中,并通过re
模块实现。 特点:
正则表达式的语法很令人头疼,可读性差; 正则表达式通用性很强,能够适用很多编程语言; 正则表达式拥有自己独特的语法以及一个独立的处理引擎(正则表达式模式被编译成一系列的字节码,然后由用C
编写的匹配引擎执行),在提供了正则表达式的语言里,正则表达式的语法都是一样的。 正则表达式语言相对小型和受限(功能有限); 并非所有字符串处理都能用正则表达式完成。
反斜杠的麻烦
In [ 1 ] : "hello\nworld"
In [ 2 ] : r"hello\nworld"
In [ 3 ] : a = "hello\nwordl"
In [ 4 ] : b = r"hello\nworld"
In [ 5 ] : print ( a)
hello
wordl
In [ 6 ] : print ( b)
hello\nworld
扩展:“\
”
用于取消所有的元字符(转译为普通符号),如:
“[]
”在正则中表示列举的字符集,如果仅仅想匹配“[]
”符号,可以使用“\[\]
”将其转译为普通符号。 “.
”在正则总表示除\n
以外的任意一个字符,如果仅仅想匹配“.
”符号,可以使用“\.
”将其转译为普通符号。 后面可以加不同的字符以表示不同特殊含义,如:
加d
、D
、w
、W
等表示特殊的字符集,具体看后面的表; 加数字,表示引用的分组编号,看下面的“匹配分组 ”; 加n
、t
等表示换行、缩进等。
正则匹配的函数
RegexObject
实例有一些方法和属性,完整的列表可查询Python Library Reference
:
如果没有匹配成功的话,match()
和search()
将返回None
; 如果成功的话,就会返回一个MatchObject
对象;
方法 作用 re.match(r"", str[,flags])
根据正则表达式从头开始匹配字符串数据 re.search(r"", str[,flages])
根据正则表达式从头到尾匹配字符串数据,匹配1次 re.findall()
找到RE
匹配的所有字串,返回一个列表(存放匹配结果字符串的列表) re.finditer()
找到RE
匹配的所有字串,返回一个迭代器(存放匹配结果MatchObject
对象的迭代器) re.split(r"","text")
按照RE
分割字符串 re.sub(r"","new","old"[,count])
根据RE
将new
替换掉old
字符串对应规则的部分,count
表示替换次数,不设置默认替换所有,最后返回替换后的字符串 re.subn(r"","new","old")
根据RE
将new
字符串替换掉old
字符串负责规则的部分,返回(替换后的字符串, 替换次数)
sub()
:正则替换字符串
rs = r'c..t'
re. sub( rs, 'python' , 'csvt caat cvvt cccc' )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
结果:'python python python cccc'
replace()
:字符串方法,替换字符串,会把正则表达式当成普通的字符串。
'csvt caat cvvt c..t cccc' . replace( 'c..t' , 'python' )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
结果:'csvt caat cvvt python cccc'
subn()
替换字符串,并返回替换了几次
rs = r'c..t'
re. subn( rs, 'python' , 'csvt caat cvvt cccc' )
结果:( 'python python python cccc' , 3 )
MatchObject
实例方法
方法 作用 obj.group()
返回被RE
匹配的字符串 obj.start()
返回匹配开始的位置 obj.end()
返回匹配结束的位置 obj.span()
返回一个元组包含匹配(开始,结束)的位置
实际程序中,最常见的做法是将MatchObject
保存在一个变量里,然后检查它是否为空。
p = re. compile ( . . . )
m = p. match( 'string goes here' )
if m:
print ( '匹配成功:' , m. group( ) )
print ( '匹配成功:' , m. group( 0 ) )
print ( '匹配成功:' , m. group( 1 ) )
print ( '匹配成功:' , m. group( 2 ) )
else :
print ( '匹配失败' )
匹配普通字符
大多数字母和字符一般都会和自身匹配,如正则表达式r"hello"
会和字符串"hello"
完全匹配。
匹配单个字符(元字符)
代码 功能 .
匹配任意1个字符(除了\n
) []
匹配[]
中列举的字符,注意:元字符在字符集中不起作用,如[akm$]
:把$
当成要匹配的字符了 [^]
不在[]
中的字符,如:[^abc]
匹配除了a,b,c
之外的字符 [-]
匹配X
到Y
之间的某个字符。[0-9]
匹配0到9之间的任一数字;[a-z]
匹配a
到z
之间的任一小写字母;[A-Z]
匹配A
到Z
之间的任一大写字母 \d
匹配十进制数字,即[0-9]
\D
匹配任何非数字字符,即[^0-9]
\s
匹配任何空白,即[\t\n\r\f\v]
如:空格、换行、tab
键等 \S
匹配任何非空白,即[^\t\n\r\f\v]
\w
匹配非特殊字符,即a-z
、A-Z
、0-9
、_
、汉字 \W
匹配特殊字符,即非字母、非数字、非汉字、非下划线
匹配多个字符(量字符)
代码 功能 *
匹配前一个字符出现0次或者无限次,不超过整数界定范围20亿{0,} +
匹配前一个字符出现1次或者无限次,即至少有1次{1,} ?
匹配前一个字符出现1次或者0次,表示某件事物是可选的{0,1} {m}
匹配前一个字符出现m
次 {m,n}
匹配前一个字符出现从m
到n
次(闭区间);忽略m
:{,n}
会认为下边界是0;忽略n
:{m,}的觉过将是上边界为无穷大;注意:{}
中不要乱加空格
扩展:“?
”
re. findall( 'ab+?' , 'abbbbbbbb' )
结果:[ 'ab' ]
re. findall( 'ab*?' , 'abbbbbbbb' )
结果:[ 'a' ]
匹配开头和结尾
代码 功能 ^
匹配字符串开头[^指定字符]
: 表示除了指定字符都匹配 $
匹配字符串结尾
匹配分组
代码 | 功能 |
| 匹配左右任意一个表达式 ()
| 作用一:在全匹配中优先输出()
中的内容,常用于爬虫;作用二:将括号中字符作为一个成为整体(分组) \num
| 引用分组num
匹配到的字符串(内容),如果正则前没写r
,就要写成\\num
,即r"\num"
<==>"\\num"
注意:匹配的是内容,不是规则 (?P<name>)
| 分组起别名 (?P=name)
| 引用别名为name
分组匹配到的字符串
()
的作用一:在全匹配中优先输出()
中得内容
s = '''hhsdj dskj hello src=csvt yes jdjsag
djcasgad src=123 yes jdsa
src=234 yes
hello src=pyhon yse kasdg '''
r1 = r"hello src=(.+ yes)"
re. findall( r1, s)
()
的作用二:让正则中得一部分成为整体,即分组
email = r"\w{3}@\w+(\.com|\.cn)"
re. match( email, zzz@xx. com')
re. match( email, 'zz@yy.cn' )
匿名分组
创建正则的分组:用户创建的分组编号是从1开始的; 分组引用:将分组匹配到的数据在正则中使用,“\编号
”表示引用第几个分组的数据。
match_obj = re. match( "<[a-zA-Z1-6]+>.*</[a-zA-Z1-6]+>" , "<html>hh</html>" )
match_obj = re. match( r"<([a-zA-Z1-6]+)>.*</\1>" , "<html>hh</html>" )
if match_obj:
print ( match_obj. group( ) )
print ( match_obj. group( 0 ) )
print ( match_obj. group( 1 ) )
else :
print ( "匹配失败" )
有名分组
创建有名分组:(?P<name>正则)
使用有名分组的引用:(?P=name)
match_obj = re. match( """"<(?P<name1>[a-zA-Z1-6]+)><(?P<name2>
[a-zA-Z1-6]+)>.*
</(?P=name2)></(P=name1)>""" ,
"<html><h1>www.itcast.cn</h1></html>" , re. X)
if match_obj:
print ( match_obj. group( ) )
else :
print ( "匹配失败" )
变异标志-flags
参数 含义 re.DOTALL
简写re.S
使.
匹配包括\n\t
等在内的所有字符 re.IGNORECASE
简写re.I
使匹配不区分大小写 re.LOCALE
简写re.L
做本地化识别(locale-awaer)
匹配.法语等“と
”或“é
” re.MULTILINE
简写re.M
多行匹配,影响^
和$
re.VERBOSE
简写re.X
能够使用REs
的verbose
状态,使之被组织得更清晰易懂(就是正则写成多行得)
re.VERBOSE
或re.X
参数:正则表达式可以写成多行
charref = re. compile ( r'''
(
[0-9]+[^0-9] # Decimal form
|0[0-7]+[^0-7] # Octal form
|x[0-9a-fA-F]+[^0-9a-fA-F] # Hexadecimal form
)
''' , re. VEROSE)
正则预编译re.compile()
re
模块提供了一个正则表达式引擎的接口,可以让你将REstring
编译成对象,并用他们来进行匹配,这样速度比直接利用正则匹配速度快 。 编译正则表达式及使用方式:
import re
tel = r"010-?\d{8}$"
p_tel = re. compile ( tel)
result_list = p_tel. findall( "010-12345678" )
result_list = re. findall( p_tel, "010-12345678" )
re.compile()
也可以接受可选的标志参数,常用来实现不同的特殊功能和语法变更,比如忽略大小写:
p = re. compile ( 'ab*' , re. IGNORECASE)