前些天一直在刷题,不过都是一些挺简单的,然后有几道需要python脚本的题可谓是把我弄了一波,认认真真地去学习了一波python以及正则。就聊一下这几道题收获吧。
Python
Requests
首先是python requests库的学习
对于request的回显如果显示乱码的话,可以添加
1 | rep.encoding = 'utf-8' |
进阶用法可以用
1 | r = requests.session() |
用来保持会话,以及可以直接实现带cookie二次访问
1 | #比如第一次建立链接 |
这就很方便了,不需要再单独记录cookie来确定是同一次session了
还有python的正则库re
1 | import re |
在re.compile引号中输入你的正则表达式,然后进行匹配
exec、eval、represents
exec语句用来执行储存在字符串或文件中的Python语句。例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句。
1 | exec("print('Hello World')") |
运行结果:
Hello World
eval语句用来计算存储在字符串中的有效Python表达式。
1 | eval_r("2 * 3") |
运行结果:
6
repr函数用来取得对象的规范字符串表示。注意,在大多数时候有eval_r(repr(object)) == object。
执行shell命令
os.system
os模块中的os.system()这个函数来执行shell命令
os.system('ls')
输出结果:
Appalication Desktop Downloads
print os.system('mkdir test')
输出结果:
0
可以看到结果打印出0,表示命令执行成功;否则表示失败(再次执行该命令,输出:子目录或文件 test 已经存在。1)
再次执行:
mkdir: test: File exists
256
注,这个方法得不到shell命令的输出。
popen()
这个方法能得到命令执行后的结果是一个字符串,要自行处理才能得到想要的信息。
1
2
3
4
5import os
str = os.popen("ls").read()
a = str.split("\n")
for b in a:
print b输出结果与
os.system('ls')
一致commands模块
可以很方便的取得命令的输出(包括标准和错误输出)和执行状态位
1
2
3
4
5
6
7
8
9
10
11
12import commands
a,b = commands.getstatusoutput('ls')
a是退出状态
b是输出的结果。
>>> import commands
>>> a,b = commands.getstatusoutput('ls')
>>> print a
0
>>> print b
Application
Desktop
Downloadscommands.getstatusoutput(cmd)返回(status,output)
commands.getoutput(cmd)只返回输出结果
commands.getstatus(file)返回ls -ld file 的执行结果字符串,调用了getoutput,不建议使用这个方法。
subprocess模块
使用subprocess模块可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态。使用subprocess模块的目的是替代os.system()、os.popen()、commands.等旧的函数或模块。
1
2
3
4
5
6
7import subprocess
subprocess.call(command, shell=True)
#会直接打印出结果。
subprocess.Popen(command, shell=True)
#也可以是subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 这样就可以输出结果了。
#如果command不是一个可执行文件,shell=True是不可省略的。
#shell=True意思是shell下执行command
正则表达式
正则表达式自己还是有点弱,主要是一些原理自己有点懒得去了解,就导致每次写正则自己都很蠢…
转载改编自:正则表达式 - 贪婪与非贪婪(惰性)(侵删)
使用场景
有时,我们想用正则匹配以某个子串开头,且以某个子串或字符结尾的子字符串,但是结尾的字串或字符在原字符串中出现了多次,但我们只想匹配从开始处到第一次出现的地方,换句话说,想得到开始和结尾之间内容最少的匹配。
正则的贪婪与非贪婪(惰性)
通常使用如下字符类描述前导字符的重复特征:
?: 告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。
+: 告诉引擎匹配前导字符1次或多次。
*: 告诉引擎匹配前导字符0次或多次。
{min, max}: 告诉引擎匹配前导字符min次到max次。min和max都是非负整数。如果有逗号而max被省略了,则表示max没有限制;如果逗号和max都被省略了,则表示重复min次。
因此 {0,} 和 * 一样,{1,} 和 + 的作用一样。
贪婪与非贪婪
贪婪 : 默认情况下,? + * {min, max}都是贪婪的,也就是说,它会根据前导字符去匹配尽可能多的内容。
非贪婪(惰性) : 非贪婪就是匹配尽可能少的内容。
原理浅析
结合实例来分析哈基于正则的引擎对文本的匹配过程。原始字符串:This is a <EM>first</EM> test
,使用正则<.+>来匹配HTML标签,期望第一次匹配得到<EM>
,第二次匹配得到</EM>
,实际却是第一次匹配就得到了<EM>first</EM>
。
来看看匹配过程,第一个记号是<
,这是一个文本字符,匹配其自身。第二个符号是.
,匹配了字符E
,然后+
一直可以匹配其余的字符,直到一行的结束。然后到了换行符,匹配失败(.不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配,即试图匹配>
。到目前为止,<.+
已经匹配了<EM>first</EM> test
。引擎会试图将>
与换行符进行匹配,结果失败了。于是引擎进行回溯。回溯后的匹配状况是 <.+
匹配 <EM>first</EM> tes
。于是引擎将>
与t
进行匹配。显然还是会失败。这个过程继续,直到 <.+
匹配 <EM>first</EM
,>
与>
匹配。于是引擎找到了一个匹配<EM>first</EM>
。记住,正则导向的引擎是急切的,所以它会急着报告它找到的第一个匹配。而不是继续回溯,即使可能会有更好的匹配,例如<EM>
。所以我们可以看到,由于+
的贪婪性,使得正则表达式引擎返回了一个最左边的最长的匹配。
如果想得到期望的结果,就需要启用非贪婪模式:<.+?>
总结:如果是贪婪匹配模式,正则引擎会一直匹配到字符串最后;当匹配为false时,就回溯以找到倒数第一个匹配位置,返回匹配结果。 如果是非贪婪匹配模式,正则引擎会匹配到符合pattern的末尾位置那个字符,然后再往后走一步,发现匹配为false时,就回溯以找到最近一个匹配为true的位置,返回匹配结果。
实例
例如,原始字符串:
1 | {"accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"},"dbGrant":{"0000031736":"READWRITE"},"dbSchemaId":"0000031737"} |
现在想把这部分敏感信息替换为空字符串:
1 | "accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"}, |
先不考虑结尾的逗号,尝试正则:"accesskey":\{.+\}
,直接匹配至原始字符串结尾的}字符,因为引擎默认会匹配尽可能多的内容。
考虑到贪婪性,将正则修改为:"accesskey":\{.+\}+?
,匹配结果一样。纳尼?难道我对贪婪性的理解有问题。梳理哈使用姿势,我期望它匹配到开始位置之后出现的第一个}字符,对应的表达式部分为}+?。套用非贪婪模式分析问题,期望对一个或多个}字符进行匹配,且匹配尽可能少的内容,但在原始串中,}字符都是分开的,没有连续,无论如何只能匹配一个单独的}字符。可见对}字符开启非贪婪模式匹配行不通。
想要匹配到开始位置之后出现的第一个}字符 也可以表达为 开始位置和末尾}字符之间的内容最少,对应正则部分修改为:.+?,完整表达式:"accesskey":\{.+?\}
,测试匹配结果,妥妥的。
以上均为转载,这里讲讲自己的实例
1 | sid=14d8f776-a969-4252-b35a-f83a807e7f2d;userName=111111111; |
目的是匹配
1 | sid=14d8f776-a969-4252-b35a-f83a807e7f2d; |
一开始自己瞎糊弄了半天,最后找到了比较接近的sid=.*;
,可是这个直接匹配到了行末,把userName一起包含进去了,这时候就要考虑到非贪婪性了,即sid=.*?;
就可以匹配到第一个遇到的;
又如
1 | 1087080534*1062477688-245892309-863670697+1430950488-2128604487+787613783-929770459-331572804*1754549713+81041939=?; |
匹配前面的算数表达式(=
前面的表达式不包括=
)
自己也瞎糊弄了好久,一开始写的是.*=
死活都包含了=,这就很烦了
然后认真去看了正则,用了[^]
,解释是
Match any character that is not in the set.
就是匹配任何不包含这个字符的字符串
所以最后是^[^=]*
还有对于
1 | 跑的还不错,给你flag吧: NzI3NTY3 |
匹配最后的base64字符串,之前考虑的是(?=:).*
但是还是老问题老是匹配了:
…?<
在python中不能用…这就比较麻烦了
然后查了一下发现可以用group
来弄,差不多就是给他们分组的意思
1 | (.*)(: )(.*) |
这就分成了三组,第一组匹配的是中文,第二组匹配的是:
,第三组匹配的就是最后的字符串,所以我们只需要提取group(3)
就好了。
Tmux配置记录
详情参考tmux配置
1 | #-- base --# |
Comments