python 之 正则

admin 2024年8月25日00:50:14评论13 views字数 10049阅读33分29秒阅读模式

前言:

之前打CTF经常性的因为不会写脚本而去手撸,这大大降低了效率,而且有的题由于时间限制,显然手撸行不通。

而不会写脚本经常是因为自己不会处理得到的数据,如何过滤、拼接。所以今天学习一下python的re模块,正则替换,以及刚刚从Li4n0学长脚本中发现的字符表替换。

正则

^元字符

字符串开始位置与匹配规则符合就匹配,否则不匹配

1234567
>>> import re>>> result = re.findall("^匹配规则","匹配规则这个字符串是否匹配")>>> print(result)['匹配规则']>>> result = re.findall("^匹配规则","匹配s规则这个字符串是否匹配")>>> print(result)[]

[^a-z]反取,

匹配出除字母外的字符,^元字符如果写到字符集里就是反取

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("[^a-z]", "匹配s规则这s个字符串是否s匹配f规则则re则则则")   #反取,匹配出除字母外的字符>>> print(result)  #以列表形式返回匹配到的字符串['匹', '配', '规', '则', '这', '个', '字', '符', '串', '是', '否', '匹', '配', '规', '则', '则', '则', '则', '则']

$元字符

字符串结束位置与匹配规则符合就匹配,否则不匹配

1234
>>>import re   #第一步,要引入re模块>>>a = re.findall("匹配规则$", "这个字符串是否匹配规则")   #字符串结束位置与匹配规则符合就匹配,否则不匹配>>>print(a)  #以列表形式返回匹配到的字符串['匹配规则']

*元字符

需要字符串里完全符合,匹配规则,就匹配,(规则里的*元字符)前面的一个字符可以是0个或多个原本字符

匹配前一个字符0或多次,贪婪匹配前导字符有多少个就匹配多少个很贪婪

如果规则里只有一个分组,尽量避免用*否则会有可能匹配出空字符串

12345678910
>>> import re>>> result = re.findall("匹配规则*","这个字符串是否匹配规则则则则则")>>> print(result)['匹配规则则则则则']>>> result = re.findall("匹配规则*","这个字符串是否匹配规")>>> print(result)['匹配规']>>> result = re.findall("匹配规则*","whether this string is matching?")>>> print(result)[]

+元字符

需要字符串里完全符合,匹配规则,就匹配,(规则里的+元字符)前面的一个字符可以是1个或多个原本字符

匹配前一个字符1次或无限次,贪婪匹配前导字符有多少个就匹配多少个很贪婪

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("匹配+", "匹配配配配配规则这个字符串是否匹配规则则则则则")   #需要字符串里完全符合,匹配规则,就匹配,(规则里的+元字符)前面的一个字符可以是1个或多个原本字符>>> print(result)  #以列表形式返回匹配到的字符串['匹配配配配配', '匹配']

?元字符,和防止贪婪匹配

需要字符串里完全符合,匹配规则,就匹配,(规则里的?元字符)前面的一个字符可以是0个或1个原本字符

匹配一个字符0次或1次

还有一个功能是可以防止贪婪匹配,详情见防贪婪匹配

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("匹配规则?", "匹配规这个字符串是否匹配规则则则则则")   #需要字符串里完全符合,匹配规则,就匹配,(规则里的?元字符)前面的一个字符可以是0个或1个原本字符>>> print(result)  #以列表形式返回匹配到的字符串['匹配规', '匹配规则']

.*?

123456789
>>> line = 'my title="sw engineer". His is "hello world"'>>> m = re.search(r'title="(.*?)"', line)>>> print m.group(1)sw engineer# 如果没有 ?, 则会抓到最长的两个双引号之间的内容>>> m = re.search(r'title="(.*)"', line)>>> 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
>>>import re   #第一步,要引入re模块>>>result = re.findall("匹配规则{3}", "匹配规则这个字符串是否匹配规则则则则则")   #{m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次>>>print(result)  #以列表形式返回匹配到的字符串打印出 ['匹配规则则则']

[]元字符,字符集

需要字符串里完全符合,匹配规则,就匹配,(规则里的 [] 元字符)对应位置是[]里的任意一个字符就匹配

字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义 恢复 特殊字符的特殊含义。

1234567
>>> import re   #第一步,要引入re模块>>> result = re.findall("匹配[a,b,c]规则", "匹配a规则这个字符串是否匹配b规则则则则则")   #需要字符串里完全符合,匹配规则,就匹配,(规则里的 [] 元字符)对应位置是[]里的任意一个字符就匹配>>> print(result)  #以列表形式返回匹配到的字符串['匹配a规则', '匹配b规则']>>> result = re.findall("匹配[a,b,c]规则\t", "匹配a规则这个字符串是否匹配b规则则则则则")>>> print(result)['匹配a规则\t']

反斜杠后边跟普通字符实现特殊功能;(即预定义字符)

预定义字符是在字符集和组里都是有用的

\d匹配任何十进制数,它相当于类[0-9]

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("\d", "匹配规则这2个字符串33是否匹配规则5则则则7则")   #\d匹配任何十进制数,它相当于类[0-9]>>> print(result)  #以列表形式返回匹配到的字符串['2', '3', '3', '5', '7']

\d+如果需要匹配一位或者多位数的数字时用

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("\d", "匹配规则这2个字符串33是否匹配规则5则则则7则")   #\d匹配任何十进制数,它相当于类[0-9]>>> print(result)  #以列表形式返回匹配到的字符串['2', '33',  '5', '7']

\D匹配任何非数字字符,它相当于类[^0-9]

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("\D", "匹配规则这2个字符串33是否匹配规则5则则则7则")   #\D匹配任何非十进制数,它相当于类[^0-9]>>> print(result)  #以列表形式返回匹配到的字符串['匹', '配', '规', '则', '这', '个', '字', '符', '串', '是', '否', '匹', '配', '规', '则', '则', '则', '则', '则']

\s匹配任何空白字符,它相当于类[\t\n\r\f\v]

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("\s", "匹配规则   这2个字符串3是否匹\n配规则5则则则7则")   #\s匹配任何空白字符,它相当于类[\t\n\r\f\v](横向制表符、换行、回车、换页、纵向制表符)>>> print(result)  #以列表形式返回匹配到的字符串['\t', ' ', ' ', '\n']

\S匹配任何非空白字符,它相当于类[^\t\n\r\f\v]

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall("\S", "匹配规则   这2个字符串3是否匹\n配规则5则则则7则")   #\S匹配任何非空白字符,它相当于类[^\t\n\r\f\v](横向制表符、换行、回车、换页、纵向制表符)>>> print(result)  #以列表形式返回匹配到的字符串['匹', '配', '规', '则', '这', '2', '个', '字', '符', '串', '3', '是', '否', '匹', '配', '规', '则', '5', '则', '则', '则', '7', '则']

\w匹配包括下划线在内任何字母数字字符,它相当于类[a-zA-Z0-9_]

1234
>>> import re   #第一步,要引入re模块>>> result = re.findall('\w',"https://www.cnblogs.com/")  #\w匹配包括下划线在内任何字母数字字符,它相当于类[a-zA-Z0-9_]>>> 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
>>> import re   #第一步,要引入re模块>>> result = re.findall('\W',"https://www.cnblogs.com/")  #\W不匹配包括下划线在内任何字母数字字符,它相当于类[^a-zA-Z0-9_]>>> print(result)  #以列表形式返回匹配到的字符串[':', '/', '/', '.', '.', '/']

()元字符,分组

也就是分组匹配,()里面的为一个组也可以理解成一个整体

如果()后面跟的是特殊元字符如 (adc)* 那么*控制的前导字符就是()里的整体内容,不再是前导一个字符

123456789101112
>>> import re   #第一步,要引入re模块#也就是分组匹配,()里面的为一个组也可以理解成一个整体>>> result = re.search("(a4)+", "a4a4a4a4a4dg4g654gb")   #匹配一个或多个a4>>> result1 = result.group()>>> print(result1)a4a4a4a4a4>>> result = re.search("a(\d+)","a45646148a49a4a456048a45gg")>>> print(result)<re.Match object; span=(0, 9), match='a45646148'>>>> result1 = result.group()>>> print(result1)a45646148

|元字符,或

|或,或就是前后其中一个符合就匹配

1234567
>>> import re   #第一步,要引入re模块>>> result = re.findall(r"你|好", "a4a4a你4aabc4a4dgg好dg4g654g")   #|或,或就是前后其中一个符合就匹配>>> print(result)['你', '好']>>> result = re.findall(r"a4a4a你|好dg4g654","a4a4a你4aabc4a4dgg好dg4g654g")>>> print(result)['a4a4a你', '好dg4g654']

r原生字符

将在python里有特殊意义的字符如\b,转换成原生字符(就是去除它在python的特殊意义),不然会给正则表达式有冲突,为了避免这种冲突可以在规则前加原始字符r

(这里还有点问题,结果不太懂,为啥第一个不输出 [a\b] )

1234567
>>> import re   #第一步,要引入re模块>>> result = re.findall(r"a\b","welcoma\b")>>> print(result)['a']>>> result = re.findall("a\b","welcoma\b")>>> 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的小屋

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月25日00:50:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   python 之 正则http://cn-sec.com/archives/3093358.html

发表评论

匿名网友 填写信息