前言:
之前打CTF经常性的因为不会写脚本而去手撸,这大大降低了效率,而且有的题由于时间限制,显然手撸行不通。
而不会写脚本经常是因为自己不会处理得到的数据,如何过滤、拼接。所以今天学习一下python的re模块,正则替换,以及刚刚从Li4n0学长脚本中发现的字符表替换。
正则
^元字符
字符串开始位置与匹配规则符合就匹配,否则不匹配
1234567 |
> import re"^匹配规则","匹配规则这个字符串是否匹配") > result = re.findall( > print(result)['匹配规则']"^匹配规则","匹配s规则这个字符串是否匹配") > result = re.findall( > print(result)[] |
[^a-z]反取,
匹配出除字母外的字符,^元字符如果写到字符集里就是反取
1234 |
#第一步,要引入re模块 > import re "[^a-z]", "匹配s规则这s个字符串是否s匹配f规则则re则则则") #反取,匹配出除字母外的字符 > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹', '配', '规', '则', '这', '个', '字', '符', '串', '是', '否', '匹', '配', '规', '则', '则', '则', '则', '则'] |
$元字符
字符串结束位置与匹配规则符合就匹配,否则不匹配
1234 |
#第一步,要引入re模块 >import re "匹配规则$", "这个字符串是否匹配规则") #字符串结束位置与匹配规则符合就匹配,否则不匹配 >a = re.findall(#以列表形式返回匹配到的字符串 >print(a) ['匹配规则'] |
*元字符
需要字符串里完全符合,匹配规则,就匹配,(规则里的*元字符)前面的一个字符可以是0个或多个原本字符
匹配前一个字符0或多次,贪婪匹配前导字符有多少个就匹配多少个很贪婪
如果规则里只有一个分组,尽量避免用*否则会有可能匹配出空字符串
12345678910 |
> import re"匹配规则*","这个字符串是否匹配规则则则则则") > result = re.findall( > print(result)['匹配规则则则则则']"匹配规则*","这个字符串是否匹配规") > result = re.findall( > print(result)['匹配规']"匹配规则*","whether this string is matching?") > result = re.findall( > print(result)[] |
+元字符
需要字符串里完全符合,匹配规则,就匹配,(规则里的+元字符)前面的一个字符可以是1个或多个原本字符
匹配前一个字符1次或无限次,贪婪匹配前导字符有多少个就匹配多少个很贪婪
1234 |
#第一步,要引入re模块 > import re "匹配+", "匹配配配配配规则这个字符串是否匹配规则则则则则") #需要字符串里完全符合,匹配规则,就匹配,(规则里的+元字符)前面的一个字符可以是1个或多个原本字符 > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹配配配配配', '匹配'] |
?元字符,和防止贪婪匹配
需要字符串里完全符合,匹配规则,就匹配,(规则里的?元字符)前面的一个字符可以是0个或1个原本字符
匹配一个字符0次或1次
还有一个功能是可以防止贪婪匹配,详情见防贪婪匹配
1234 |
#第一步,要引入re模块 > import re "匹配规则?", "匹配规这个字符串是否匹配规则则则则则") #需要字符串里完全符合,匹配规则,就匹配,(规则里的?元字符)前面的一个字符可以是0个或1个原本字符 > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹配规', '匹配规则'] |
.*?
123456789 |
'my title="sw engineer". His is "hello world"' line = r'title="(.*?)"', line) m = re.search(print m.group(1)sw engineer# 如果没有 ?, 则会抓到最长的两个双引号之间的内容r'title="(.*)"', line) m = re.search(print m.group(1)sw engineer". His is "hello world |
{}元字符,范围
需要字符串里完全符合,匹配规则,就匹配,(规则里的 {} 元字符)前面的一个字符,是自定义字符数,位数的原本字符
{m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次
{0,}匹配前一个字符0或多次,等同于*元字符{+,}匹配前一个字符1次或无限次,等同于+元字符{0,1}匹配前一个字符0次或1次,等同于?元字符
1234 |
#第一步,要引入re模块 >import re "匹配规则{3}", "匹配规则这个字符串是否匹配规则则则则则") #{m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次 >result = re.findall(#以列表形式返回匹配到的字符串 >print(result) 打印出 ['匹配规则则则'] |
[]元字符,字符集
需要字符串里完全符合,匹配规则,就匹配,(规则里的 [] 元字符)对应位置是[]里的任意一个字符就匹配
字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义 恢复 特殊字符的特殊含义。
1234567 |
#第一步,要引入re模块 > import re "匹配[a,b,c]规则", "匹配a规则这个字符串是否匹配b规则则则则则") #需要字符串里完全符合,匹配规则,就匹配,(规则里的 [] 元字符)对应位置是[]里的任意一个字符就匹配 > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹配a规则', '匹配b规则']"匹配[a,b,c]规则\t", "匹配a规则这个字符串是否匹配b规则则则则则") > result = re.findall( > print(result)['匹配a规则\t'] |
反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
预定义字符是在字符集和组里都是有用的
\d匹配任何十进制数,它相当于类[0-9]
1234 |
#第一步,要引入re模块 > import re "\d", "匹配规则这2个字符串33是否匹配规则5则则则7则") #\d匹配任何十进制数,它相当于类[0-9] > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['2', '3', '3', '5', '7'] |
\d+如果需要匹配一位或者多位数的数字时用
1234 |
#第一步,要引入re模块 > import re "\d", "匹配规则这2个字符串33是否匹配规则5则则则7则") #\d匹配任何十进制数,它相当于类[0-9] > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['2', '33', '5', '7'] |
\D匹配任何非数字字符,它相当于类[^0-9]
1234 |
#第一步,要引入re模块 > import re "\D", "匹配规则这2个字符串33是否匹配规则5则则则7则") #\D匹配任何非十进制数,它相当于类[^0-9] > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹', '配', '规', '则', '这', '个', '字', '符', '串', '是', '否', '匹', '配', '规', '则', '则', '则', '则', '则'] |
\s匹配任何空白字符,它相当于类[\t\n\r\f\v]
1234 |
#第一步,要引入re模块 > import re "\s", "匹配规则 这2个字符串3是否匹\n配规则5则则则7则") #\s匹配任何空白字符,它相当于类[\t\n\r\f\v](横向制表符、换行、回车、换页、纵向制表符) > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['\t', ' ', ' ', '\n'] |
\S匹配任何非空白字符,它相当于类[^\t\n\r\f\v]
1234 |
#第一步,要引入re模块 > import re "\S", "匹配规则 这2个字符串3是否匹\n配规则5则则则7则") #\S匹配任何非空白字符,它相当于类[^\t\n\r\f\v](横向制表符、换行、回车、换页、纵向制表符) > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['匹', '配', '规', '则', '这', '2', '个', '字', '符', '串', '3', '是', '否', '匹', '配', '规', '则', '5', '则', '则', '则', '7', '则'] |
\w匹配包括下划线在内任何字母数字字符,它相当于类[a-zA-Z0-9_]
1234 |
#第一步,要引入re模块 > import re '\w',"https://www.cnblogs.com/") #\w匹配包括下划线在内任何字母数字字符,它相当于类[a-zA-Z0-9_] > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) ['h', 't', 't', 'p', 's', 'w', 'w', 'w', 'c', 'n', 'b', 'l', 'o', 'g', 's', 'c', 'o', 'm'] |
\W匹配非任何字母数字字符包括下划线在内,它相当于类[^a-zA-Z0-9_]
1234 |
#第一步,要引入re模块 > import re '\W',"https://www.cnblogs.com/") #\W不匹配包括下划线在内任何字母数字字符,它相当于类[^a-zA-Z0-9_] > result = re.findall(#以列表形式返回匹配到的字符串 > print(result) [':', '/', '/', '.', '.', '/'] |
()元字符,分组
也就是分组匹配,()里面的为一个组也可以理解成一个整体
如果()后面跟的是特殊元字符如 (adc)* 那么*控制的前导字符就是()里的整体内容,不再是前导一个字符
123456789101112 |
#第一步,要引入re模块 > import re #也就是分组匹配,()里面的为一个组也可以理解成一个整体"(a4)+", "a4a4a4a4a4dg4g654gb") #匹配一个或多个a4 > result = re.search( > result1 = result.group() > print(result1)a4a4a4a4a4"a(\d+)","a45646148a49a4a456048a45gg") > result = re.search( > print(result)<re.Match object; span=(0, 9), match='a45646148'> > result1 = result.group() > print(result1)a45646148 |
|元字符,或
|或,或就是前后其中一个符合就匹配
1234567 |
import re #第一步,要引入re模块r"你|好", "a4a4a你4aabc4a4dgg好dg4g654g") #|或,或就是前后其中一个符合就匹配 result = re.findall( print(result)['你', '好']r"a4a4a你|好dg4g654","a4a4a你4aabc4a4dgg好dg4g654g") result = re.findall( print(result)['a4a4a你', '好dg4g654'] |
r原生字符
将在python里有特殊意义的字符如\b,转换成原生字符(就是去除它在python的特殊意义),不然会给正则表达式有冲突,为了避免这种冲突可以在规则前加原始字符r
(这里还有点问题,结果不太懂,为啥第一个不输出 [a\b] )
1234567 |
import re #第一步,要引入re模块r"a\b","welcoma\b") result = re.findall( print(result)['a']"a\b","welcoma\b") result = re.findall( print(result)['a\x08'] |
Re
result = re.method(“rule”,string)
1. match()方法, 从字符串头部开始匹配
12345678 |
import recontent = 'The 123456 is my one phone number.'print(len(content)) #字符串长度result = re.match(r'^The\s\d+\s\w*', content) #使用match匹配, 第一个参数为正则表达式, 第二个为要匹配的字符串print(result)print(result.group()) #输出匹配内容print(result.span()) #输出匹配内容的位置索引 |
结果:
1234 |
34<_sre.SRE_Match object; span=(0, 13), match='The 123456 is'>The 123456 is(0, 13) |
2. 匹配目标
在正则表达式中用()括起来可以使用group()输出, 若有n个(), 那么可以表示为group(n), 输出第n个括号匹配的内容.
123456789 |
import recontent = 'The 123456 is my one phone number.'print(len(content)) #字符串长度result = re.match(r'^The\s(\d+)\sis', content) #使用match匹配, 第一个参数为正则表达式, 第二个为要匹配的字符串print(result)print(result.group()) #输出匹配内容print(result.group(1)) #输出第一个被()包裹的内容print(result.span()) #输出匹配内容的位置索引 |
结果
12345 |
34<_sre.SRE_Match object; span=(0, 13), match='The 123456 is'>The 123456 is123456(0, 13) |
3.通用匹配
. 表示匹配任意字符, *表示匹配前面字符无限次.
1234567 |
import recontent = 'The 123456 is my one phone number.'result = re.match(r'^The.*number.$', content) #使用match匹配, 第一个参数为正则表达式, 第二个为要匹配的字符串print(result)print(result.group()) #输出匹配内容print(result.span()) #输出匹配内容的位置索引 |
结果
123 |
<_sre.SRE_Match object; span=(0, 34), match='The 123456 is my one phone number.'>The 123456 is my one phone number.(0, 34) |
4.贪婪与非贪婪
123456789101112131415 |
import recontent = 'The 123456 is my one phone number.'print('贪婪匹配:')result = re.match(r'^The.*(\d+).*', content) #使用match匹配, 第一个参数为正则表达式, 第二个为要匹配的字符串print(result.group()) #输出匹配内容print('result = %s'%result.group(1)) #输出第一个被()包裹的内容print('-'*20)print('非贪婪匹配:')result = re.match(r'^The.*?(\d+).*', content) print(result.group())print('result = %s'%result.group(1))print('-'*20)result = re.match(r'^The.*?(\d+).*?', content)print(result.group()) |
结果
123456789 |
贪婪匹配:The 123456 is my one phone number.result = 6--------------------非贪婪匹配:The 123456 is my one phone number.result = 123456--------------------The 123456 |
5.修饰符 re.S
由于加上re.S参数后, 通配符 . 将可以匹配换行符, 所以result不为空, result2为空。除了re.S, 还有许多修饰符如,
re.I: 使用匹配时忽略大小写。(大写的i)
123456789101112131415 |
import recontent = '''The 123456 isone of my phone.'''result = re.match('^The.*?(\d+).*?phone.', content, re.S)if result: print(result.group(1))else: print('result = None')result2 = re.match('^The.*?(\d+).*?phone.', content)if result2: print(result2.group(1))else: print('result2 = None') |
结果
12 |
123456result2 = None |
6.转义匹配
由于()属于正则表达式的特殊字符, 因此在需要匹配()时, 需要加上转义字符’’.
12345678910111213 |
import recontent = '(百度)www.baidu.com'result = re.match('(百度)www.baidu.com', content)result2 = re.match('\(百度\)www\.baidu\.com', content)if result: print(result.group())else: print('result = None')if result2: print(result2.group())else: print('result2 = None') |
结果
12 |
result = None(百度)www.baidu.com |
7.search()方法, 与match()方法不同, 不需要从头部开始匹配
12345 |
import recontent = 'Other The 123456 is my one phone number.'result = re.search('The.*?(\d+).*?number.', content)print(result.group()) |
结果
1
|
The 123456 is my one phone number.
|
8.findall()方法
match()和search()都是返回匹配到的第一个内容就结束匹配, findall()是返回所有符合匹配规则的内容
12345678910111213141516171819202122232425262728 |
import rehtml = '''<div id="songs-list"><h2 class="title">歌单</h2><p class="introduction">歌单列表</p><ul id="list" class="list-group"><li data-view="2">一路上有你</li><li data-view="7"><a href="/2.mp3" singer="任贤齐">沧海一声笑</a></li><li data-view="4" class="active"><a href="/3.mp3" singer="齐秦">往事随风</a></li><li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li><li data-view="5"><a href="/5.mp3" singer="程慧玲">记事本</a></li><li data-veiw="5"><a href="/6.mp3" singer="邓丽君">但愿人长久</a></li></ul></div>'''result = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)if result: print(result) for res in result: print(res[0], res[1], res[2]) |
结果
123456 |
[('/2.mp3', '任贤齐', '沧海一声笑'), ('/3.mp3', '齐秦', '往事随风'), ('/4.mp3', 'beyond', '光辉岁月'), ('/5.mp3', '程慧玲', '记事本'), ('/6.mp3', '邓丽君', '但愿人长久')]/2.mp3 任贤齐 沧海一声笑/3.mp3 齐秦 往事随风/4.mp3 beyond 光辉岁月/5.mp3 程慧玲 记事本/6.mp3 邓丽君 但愿人长久 |
9.sub()方法, 去除匹配的字符
第二个参数是两个’,表示吧’\d+‘ 匹配的内容替换成空,如果写sub(’\d+’, ‘?’), 则把匹配的内容替换成 ?。
123456789 |
import recontent = '54abc59de335f7778888g'result = re.sub('\d+', '', content)print(result)result = re.sub('\d', '?', content)print(result)result = re.sub('\d+', '?', content)print(result) |
结果
123 |
abcdefg??abc??de???f???????g?abc?de?f?g |
有点像replace,但是多一个正则关系匹配
10.compile()
在需要匹配相同正则表达式情况下, 事先定义一个compile可以简化代码量, 同时compile中也可以使用修饰符re.S等.
( 其实也可以直接a=rule,然后 result = re.findall(a,string) ,但是这样子就不能用修饰符re.S了)
1234567891011 |
import recontent1 = '2016-1-1 12:01'content2 = '2017-1-1 12:02'content3 = '2018-1-1 12:03'pattern = re.compile('\d{2}:\d{2}')result1 = re.sub(pattern, '', content1)result2 = re.sub(pattern, '', content2)result3 = re.sub(pattern, '', content3)print(result1, result2, result3) |
结果
1
|
2016-1-1 2017-1-1 2018-1-1
|
附一手去除列表空元素的方法:
1
|
mytest = [i for i in test if i != '']
|
番外
这里记一下从从Li4n0学长脚本中发现的字符表替换函数:maketrans()
语法:str.maketrans(intab, outtab)
参数:
intab – 字符串中要替代的字符组成的字符串
outtab – 相应的映射字符的字符串。
配合str.translate使用
实例
123456 |
intab = "aeiou"outtab = "4310U"transtab = str.maketrans(intab, outtab)content = "this is string example....wow!!!"print (content.translate(transtab)) |
结果
1
|
th1s 1s str1ng 3x4mpl3....w0w!!!
|
参考资料:
https://blog.csdn.net/qq_38038143/article/details/80671420
https://www.cnblogs.com/zjltt/p/6955965.html
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 [email protected] - source:Van1sh的小屋
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论