Python正则表达式

在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤⼀个python自带的模块,名字为re。

re模块的使用:import re

正则表达式的大致匹配过程是:

1.依次拿出表达式和文本中的字符比较,

2.如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。

3.如果表达式中有量词或边界,这个过程会稍微有一些不同。

匹配字符

字符功能
.匹配任意1个字符(除了\n)
\d匹配一个数字,即0-9
\D匹配非数字,即不是数字
\s匹配空白,即空格,tab键
\S匹配非空白字符
\w匹配一个字母或数字
\W匹配非单词数字字符
*表示任意个字符(包括0个)
+表示至少一个字符
?表示0个或1个字符
{n}表示n个字符
{n,m}表示n-m个字符

例子一

\d{3}\s+\d{3,8}

1、\d{3}表示匹配3个数字,例如'010'

2、\s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配' '' '等;

3、\d{3,8}表示3-8个数字,例如'1234567'

上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码

010 12345

如果要匹配'010-12345'这样的号码,由于'-'是特殊字符,在正则表达式中,要用'\'转义,所以,上面的正则是\d{3}\-\d{3,8}

字符功能例子
[]表示范围[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线
A|B可以匹配A或B(P|p)ython可以匹配'Python'或者'python'
^行的开头^\d表示必须以数字开头
$行的结束\d$表示必须以数字结束
  • [0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;
  • [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100''0_Z''Py3000'等等;
  • [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;
  • [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。

re模块

r前缀

r:在带有 'r' 前缀的字符串字面值中,反斜杠不必做任何特殊处理。

由于Python的字符串本身也用\转义,所以要特别注意

s = 'ABC\\-001' # Python的字符串
# 对应的正则表达式字符串变成:
# 'ABC\-001'

使用r前缀后,就不用考虑转义问题

s = r'ABC\-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC\-001'

re.match函数

re.match(pattern, string, flags=0)

pattern匹配的正则表达式
string要匹配的字符串
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 re.I 忽略大小写 re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境 re.M 多行模式 re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符) re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库 re.X 为了增加可读性,忽略空格和 # 后面的注释

例一

match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。常见的判断方法就是:

import re
text = '1234aa'
if re.match(r'1234AA',text,re.I):
   print('ok')
else:
   print('fail')

由于忽略大小写(re.I),所以输出ok

例二

group()用来提出分组截获的字符串,()用来分组,group() 同group(0)就是匹配正则表达式整体结果,group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。没有匹配成功的,re.search()返回None。

import re
ret = re.match("([^-]*)-(\d+)","010-12345678")
print(ret.group())
print(ret.group(1))
print(ret.group(2))

输出

010-12345678 010 12345678

例三

import re
email_list = ["123@qq.com", "123@163.com", "654@cloud.com","645@baidu.com"]
for email in email_list:
   ret = re.match("\d{3,10}@(qq|163|cloud)\.com$", email)
   if ret:
       print("%s 是符合规定的地址,匹配后的结果是:%s" % (email, ret.group()))
   else:
           print("%s 不符合要求" % email)

匹配出qq、163、cloud的邮箱

例四

import re
tels = ["13100001234", "18912344321", "10086", "18800007777"]
for tel in tels:
   ret = re.match("1\d{9}[0-35-68-9]", tel)
   if ret:
       print(ret.group())
   else:
       print("%s 不是想要的⼿机号" % tel)

提取不是以4、7结尾的⼿机号码(11位),其中[0-35-68-9]表示范围,0~3、5~6等,不用分隔符分开

例五

import re
# 正确的理解思路:如果在第⼀对<>中是什么,按理说在后⾯的那对<>中就应该是什么。通过引⽤分组中匹配到的数据即可,但是要注意是元字符串,即类似 r""这种格式。
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>")
# 因为2对<>中的数据不⼀致,所以没有匹配出来
test_label = ["<html>hh</html>","<html>hh</htmlbalabala>"]
for label in test_label:
   ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", label)
   if ret:
       print("%s 这是一对正确的标签" % ret.group())
   else:
       print("%s 这是⼀对不正确的标签" % label)

\1,…,\9,匹配第n个分组的内容。如例子所示,指匹配第一个分组的内容。

<html>hh</html> 这是一对正确的标签 <html>hh</htmlbalabala> 这是⼀对不正确的标签

re.split函数

根据匹配进⾏切割字符串,并返回⼀个列表。

re.``split(pattern, string, maxsplit=0, flags=0)

参数描述
pattern匹配的正则表达式
string要匹配的字符串
maxsplit分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数

例子

import re
ret = re.split(r":| ","info:xiaoZhang 33 shandong")
print(ret)

输出

['info', 'xiaoZhang', '33', 'shandong']

re.findall函数

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。注意 match 和 search 是匹配一次 findall 匹配所有。

import re
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret)

输出

['9999', '7890', '12345']

match与findall

match:

从开头位置匹配,只匹配一次,开头匹配不上,则不继续匹配 a,b,\w+

match(a,"abcdef") 匹配a

\>>> re.match("a","abcdef").group()

'a'

match(b,"abcdef")

\>>> print re.match("b","abcdef")

None

match("\w+","abcdef")

findall

注:findall 返回列表 ,列表不能group()

\>>> print re.findall(r"b","abcdef abc 123 456")

['b', 'b']


\>>> print re.findall(r"a","abcdef abc 123 456")

['a', 'a']
 
\>>> print re.findall(r"\w+","abcdef abc 123 456")

['abcdef', 'abc', '123', '456']

输出带有[0]就可以输出str类型,如print result[0]输出第一个匹配到的str类型

python贪婪和⾮贪婪

Python⾥数量词默认是贪婪的(在少数语⾔⾥也可能是默认⾮贪婪),总是尝试匹配尽可能多的字符;⾮贪婪则相反,总是尝试匹配尽可能少的字符。

例如:正则表达式”ab”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab?”,将找到”a”。

注:我们一般使用非贪婪模式来提取。

在”*”,”?”,”+”,”{m,n}”后⾯加上?,使贪婪变成⾮贪婪。

例一

import re
s="This is a number 234-235-22-423"
#正则表达式模式中使⽤到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满⾜匹配最⻓字符串,在我们上⾯的例⼦⾥⾯,“.+”会从字符串的启始处抓取满⾜模式的最⻓字符,其中包括我们想得到的第⼀个整型字段的中的⼤部分,“\d+”只需⼀位字符就可以匹配,所以它匹配了数字“4”,⽽“.+”则匹配了从字符串起始到这个第⼀位数字4之前的所有字符
r=re.match(".+(\d+-\d+-\d+-\d+)",s)
print(r.group(1))
#⾮贪婪操作符“?”,这个操作符可以⽤在"*","+","?"的后⾯,要求正则匹配的越少越好
r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
print(r.group(1))

结果:

4-235-22-423 234-235-22-423

例二

import re
test_str="<img data-original=https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973.jpg>"
ret = re.search(r"https://.*?.jpg", test_str)
print(ret.group())

结果:https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973.jpg

例题

例一

中科大2017信息安全大赛 真假flag

打开一段乱的flag,真的flag藏在其中

image-20210808220206744

用python的正则表达式去匹配

import re
f = open("flag.txt","rb")
txts = f.readlines()
f.close()
for txt in txts:
    txt = str(txts)
    flag = re.findall("flag\{\w+}",txt)
    print(flag[0])

例二

bugku 秋名山车神

img

2s刷新一次,查看源码

img

写python脚本获取页面数据并计算post提交结果获得flag

import re
import requests

sess = requests.session()
response = sess.get("http://114.67.246.176:17986/").text
calc = eval(re.findall(r"(\d+[+\-*])+(\d+)",response)[0])
key = {
    'value':calc
}
flag = sess.post("http://114.67.246.176:17986/",data=key)
print(flag.text)

例三

[强网杯 2019]高明的黑客

下载之后是几千个php文件,里面有各种shell

不过很多shell都没用,但肯定存在几个shell可以用,只能跑脚本去尝试

import os
import requests
import re
import threading
import time
print('开始时间:  '+  time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100)  							  			#这儿设置最大的线程数
filePath = r"D:/soft/phpstudy/PHPTutorial/WWW/src/"
os.chdir(filePath)													#改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5								#设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False											 # 设置连接活跃状态为False
def get_content(file):
    s1.acquire()												
    print('trying   '+file+ '     '+ time.asctime( time.localtime(time.time()) ))
    with open(file,encoding='utf-8') as f:							#打开php文件,提取所有的$_GET和$_POST的参数
            gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
            posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
    data = {}														#所有的$_POST
    params = {}														#所有的$_GET
    for m in gets:
        params[m] = "echo 'xxxxxx';"
    for n in posts:
        data[n] = "echo 'xxxxxx';"
    url = 'http://127.0.0.1/src/'+file
    req = session.post(url, data=data, params=params)			#一次性请求所有的GET和POST
    req.close()												# 关闭请求  释放内存
    req.encoding = 'utf-8'
    content = req.text
    #print(content)
    if "xxxxxx" in content:									#如果发现有可以利用的参数,继续筛选出具体的参数
        flag = 0
        for a in gets:
            req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
            content = req.text
            req.close()												# 关闭请求  释放内存
            if "xxxxxx" in content:
                flag = 1
                break
        if flag != 1:
            for b in posts:
                req = session.post(url, data={b:"echo 'xxxxxx';"})
                content = req.text
                req.close()												# 关闭请求  释放内存
                if "xxxxxx" in content:
                    break
        if flag == 1:													#flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
            param = a
        else:
            param = b
        print('找到了利用文件: '+file+"  and 找到了利用的参数:%s" %param)
        print('结束时间:  ' + time.asctime(time.localtime(time.time())))
    s1.release()

for i in files:															#加入多线程
   t = threading.Thread(target=get_content, args=(i,))
   t.start()
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇