正则表达式
简介
-
简称RE,reg,regexp…
-
它的设计思想是用
一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,
我们就认为它“匹配”了,否则,该字符串就是不合法的。
精确匹配
\d
匹配一个数字
\d\d\d – 777
\w
匹配一个字符
\w\w\d – py3
.
可以匹配任意字符
py. --py3 pyc py2
- 匹配变长的字符时,
*
表示任意个字符(包括0个),?
表示0个或1个字符,{n}
表示n的字符,{n,m}
表示n-m个字符
\d{3}\s+\d{3,8}
\d{3} 表示匹配三个数字
\s 匹配一个空格或Tab等空白字符
\d{3-8} 表示匹配3-8个数字
010-12345 中间有个空格,用
\
转义,使用\d{3}\-\d{3,8}
精准匹配进阶
-
[]
表示范围 -
[0-9a-zA-Z\_]
可以匹配一个数字,字母(不区分大小写),下划线 -
[0-9a-zA-Z\_]+
可以匹配至少一由一个数字,字母,下划线组成的字符串。eg:a0999,8_90,a,Id9a -
[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}
第一个字符是字母或者下划线,后面最多匹配19位 -
A|B
匹配A或B,[p|P]ython
可以匹配python和Python -
^
表示开头,^\d 表示以数字开头 -
$
表示结尾,\d$ 表示数字结尾 -
*
匹配前一个字符单元0次或多次 -
+
匹配前一个字符单元1次或多次
re模块的使用(python
- 导入:
import re
- 编写时应该注意
\
在python里表示转义,则\d\\-\w
表示\d\-\w
,但是在字符串前使用r前缀,就不用考虑转义的问题了:s = r'\d\-\w'
re模块-如何匹配
match()方法
- 关于返回值:如果没有匹配到会返回None
import re
t1 = '007'
t2 = 'rdd'
print(re.match(r1,t1))
# out:<re.Match object; span=(0, 3), match='007'>
print(type(re.match(r1,t1)))
# out:<class 're.Match'>
print(re.match(r1,t2))
# out:None
print(type(re.match(r1,t2)))
# out:<class 'NoneType'>
- 实例:检测字符串是否是三位数字
import re
t1 = '007'
t2 = 'rdd'
r1 = r'\d\d\d'
if re.match(r1,t1):
print('[*] {}:是三个数字'.format(t1))
else:
print('[*] {}:不是三个数字'.format(t1))
切分字符串
- 在python切分字符串时,最常用的是
split
方法,例如'a b c d'.split(' ')
,是以空格切割字符串,但是回显结果是['a', 'b', 'c', '', '', 'd']
,说明遇到连续空格时,split并不能很好的分割 - 可以使用re.split,来解决这种情况
import re
s = 'a b c d e'
r = r'\s+'
print(re.split(r,s))
- 当分隔符不唯一时
import re
s1 = 'a,b,c ,d e'
r1 = r'[\s\,]+'
print(re.split(r1,s1))
s2 = 'a,b;c ,d e'
r2 = r'[\s\,\;]+'
print(re.split(r2,s2))
分组
-
()
表示分组 -
实例:提取账户名和邮箱类型
import re
t1 = 'rdd_null@163.com'
r1 = r'([0-9A-Za-z\_]+)\@([0-9A-Za-z\_]+\.[0-9A-Za-z\_]+)'
res = re.match(r1,t1)
if res:
print('邮箱是:'+res.group(0))
print('账号是:'+res.group(1))
print('邮箱类型是:'+res.group(2))
else:
print(t1+'不是一个邮箱')
贪婪匹配
-
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符
-
例如:
re.match(r’^(\d+)(0*)$’,‘102300’).groups()
out:(‘102300’, ‘’)
-
(\d+)是贪婪匹配,一直匹配到0,所以(0*)什么都匹配不到
-
要想使后面的0也匹配出来,就要采取非贪婪匹配,把
(\d+)
改为(\d+?)
re.match(r’^(\d+?)(0*)$’, ‘102300’).groups()
out:(‘1023’, ‘00’)
编译
-
当我们在python中使用正则表达式时,re模块会:编译正则表达式,如果正则表达式的字符串本身不合法,会报错;用编译后的正则表达式去匹配字符串。
-
如果一个正则表达式要使用成千上万次,为了效率,我们可以预编译该正则表达式
-
使用
re.compile
-
实例:去出所有的qq邮箱
import re
t1 = 'rdd_null@163.com@qq.com;741153347@qq.com;890179463@qq.com;7413347@q.com'
mail_list = re.split(r"[\;]+",t1)
tmp = r'([a-zA-Z0-9\_]+)\@qq.com$'
r2 = re.compile(tmp)
for mail in mail_list:
res = r2.match(mail)
if res:
print('[*]{} 是qq邮箱'.format(mail))
else:
print('[*]{} 不是qq邮箱'.format(mail))
应用
awd中匹配合法flag
import re
flags = """flag{4502722e-bc78-3fde-8b78-3ff9ba827ed8}
flag{4502722e-bc78-3fde-8b78-3ff9ba827ed}
flag{4502722e-bc78-3fde-8b783ff9ba827ed8}
flag{whatareudoing}
flag{ccc}
flag{4502722e-bc78-3fde-8b78-3ff9ba827ed9}
flag{4502722e-bc78-3fde-8b78-3ff9ba827ed8}
flag{4502722e-bc78-3fde-8b78-3ff9ba827e
lag{4502722e-bc78-3fde-8b78-3ff9ba827ed8}"""
def find_flags(flags):
flag_list = flags.split('\n')
tmp = r'flag{([a-z0-9]{8})\-([a-z0-9]{4})\-([a-z0-9]{4})\-([a-z0-9]{4})\-([a-z0-9]{12})\}'
reg_flag = re.compile(tmp)
true_flags = []
for flag in flag_list:
res = reg_flag.match(flag)
if res:
print('[*]true flag:{}'.format(flag))
true_flags.append(flag)
else:
print('[*]fake flag:{}'.format(flag))
return true_flags
true_flags = find_flags(flags)
print('all flag:{}'.format(true_flags))