一、%相关
x=100
print('%o'%x) #八进制
print('%d'%x) #十进制
print('%x'%x) #十六进制
print('%e' % x) # 指数
print(list('%s' % [1, 2, 3])) # 转为字符串
144
100
641.000000e+02
['[', '1', ',', ' ', '2', ',', ' ', '3', ']']
二、format槽{}
若{}里面无数字标号,则默认的从左到右。
print('{}CPU的利用率为{},售价为{}'.format('i7-10750H', '80%', 6896))
i7-10750HCPU的利用率为80%,售价为6896
正正规规的槽是有很多参数的,参照下面完整的槽定义。功能很强大。
#1.测试数字标号
print('{1}喜欢{0}'.format('漂亮姐姐', '我'))
#我喜欢漂亮姐姐
#2.测试对齐、宽度和字符填充
print('{1:$<8}喜欢{0:#>10}'.format('漂亮姐姐', '我'))
#我$$$$$$$喜欢######漂亮姐姐
#1号槽表示填充字符是$,左对齐,长度为8位。0号槽表示填充字符是#,右对齐,长度是10
#测试千位分隔符,和精度设置,以及数字类型。
print('第一次{0:*<8.2f},第二次{1:,d}'.format(3.8554, 100000000))
#第一次3.86****,第二次100,000,000
还有几个零碎的小点。
'''#x在十六进制数字前面加上0x,#o同理,必须加#,否则不起作用''' print("The number {0:,} in hex is: {0:#x}, the number {1} in oct is {1:#o}".format(5555, 55)) '''<左对齐,^居中,>右对齐''' print('{0:<8d},{0:^8d},{0:>8d}'.format(65))
3.6之后出现了一个新的格式化:
name = 'T^T' age = 10 print(f'他的名字叫{name},年龄{age}') # 他的名字叫T^T,年龄10
三、字符串相关函数
1.join()
yymmdd = ['2011', '10', '3'] print('-'.join(yymmdd))
2.split可以指定最大分割次数.对于split()和rsplit0方法,如果不指定分隔符,则字符串中的任何空白符号(空格、换行符、制表符等)都将被认为是分隔符,把连续多个空白字符看作一个分隔符。
str = '冰,哥,一,晃,把,你,晃,死' print(str.split(',', 2))
['冰', '哥', '一,晃,把,你,晃,死']
3.replace函数
str='你就是个大傻逼,智障都比你强' words=['大傻逼','智障','比'] for i,word in enumerate(words): str=str.replace(word,'**') print(str)
4.字符串映射maketrans()和translate()方法。例如CTF的替换密码
orin = 'abcdefghigklmnopqlstuvwxyz' repl = 'qwertyuiopasdfghjklzxcvbnm' table = ''.maketrans(orin, repl) plain_text = 'i love you' cliper_text=plain_text.translate(table) print(cliper_text)
o kgct ngx
5.开头结尾检测函数。s.startswith(t)Ƚ s.endswith(t)判断s的开头/结尾是否是t。
s = 'Do you Love me?' print(s.startswith('Do')) print(s.endswith('me?')) print([filename for filename in os.listdir(r'C:\Users\DELL\Desktop\pythonprojet\Python实验\实验2')\ if filename.endswith('.py')])
6.字符集合,以后写脚本就不用写for循环再chr取字符了。
import string print(string.ascii_letters) print(string.ascii_lowercase) print(string.ascii_uppercase) # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ # abcdefghijklmnopqrstuvwxyz # ABCDEFGHIJKLMNOPQRSTUVWXYZ import string import random #随机生成一个flag串 str_list = list(string.ascii_letters) random_flag = 'flag{' + ''.join(random.choices(str_list, k=25)) + '}' print(random_flag)
四、正则表达式
先介绍什么是分组?
例如'(+86)+\d{11}'
前面在讲重复时,都是重复某个字符,如果想要让一个字符串重复呢,就如本题中的+86,它作为一个整体重复0次或1次,就需要用小括号把+86括起来,(+86) 就变成了一个分组,也叫子表达式,在使用正则表达式匹配时,这些分组的部分如果被匹配上,我们就可以通过编号或者名字获得分组中中匹配的字符串。
re模块的具体方法。
1.re.split()
text = 'alpha. beta....gamma delta' # .有特殊含义,所以得加\ result = re.split('[\.]+', text) print(result) # 说明:如果加上括号,结果会同时返回去掉的值 result = re.split('([\.])+', text) print(result) result = re.split('([\.]+)', text) print(result)
['alpha', ' beta', 'gamma delta']
['alpha', '.', ' beta', '.', 'gamma delta']
['alpha', '.', ' beta', '....', 'gamma delta']
2.findall()
text = 'alpha. beta....gamma delta' words = re.findall('[a-zA-Z]+', text) print(words) #['alpha', 'beta', 'gamma', 'delta'] example = 'Beautiful is better than ugly.' re_sub = re.findall('\\b.+?\\b', example) #贪心模式 ['Beautiful', ' ', 'is', ' ', 'better', ' ', 'than', ' ', 'ugly'] re_sub = re.findall('\\b.+\\b', example) #非贪心模式 ['Beautiful is better than ugly'] example = 'Beautiful is better than ugly.' re_sub = re.findall('\\Bh\w+\\b', example) # 贪心模式,不已h开头却含有h的单词剩余部分 ['han'] print(re_sub)
3.group函数。
# 不加括号,整体一大个作为一个分组 pattern = re.compile('\d-\d-\d') match = pattern.match('1-8-6') print(match.group(1)) #报错,因为一个整体的话不存在group(1) Traceback (most recent call last): File "C:\Users\DELL\Desktop\pythonprojet\Python实验\2022_1_10.py", line 13, in <module> print(match.group(1)) IndexError: no such group # 设置了三个小分组 pattern = re.compile('(\d)-(\d)-(\d)') match = pattern.match('1-8-6') print(match.group(0,1,2,3)) #('1-8-6', '1', '8', '6') # 甚至可以给每个小分组取名字?P<name> pattern = re.compile('(?P<first>\d)-(?P<second>\d)-(\d)') match = pattern.match('1-8-6') print(match.group('first','second')) #('1', '8')
4.sub(x,s,maxsplit=)函数.。(subn只不过多了一个返回的参数而已,他会把替换的次数也返回)
返回一个字符串。每一个匹配的地方用x进行替换,返回替换后的字符串,如果指定m,则最多替换maxsplit次。对于x可以使用/i或者/g<id>id可以是组名或者编号来引用捕获到的内容。
pat = '{name}' text = 'Dear {name}...' print(re.sub(pat,'LIUHQ',text)) #Dear LIUHQ...
甚至模块方法re.sub(r, x, s, m)中的x可以使用一个函数。此时我们就可以对捕获到的内容推过这个函数进行处理后再替换匹配到的文本。参考下面的例子:
def check_Modify(s): return re.sub(r'\b(\w)(\w+)(\w)\b', lambda x: x.group(1) + x.group(2).lower() + x.group(3), s) print(check_Modify('aBc ABBC D eeee fFFFfF')) #aBc AbbC Deeee fFFFfF
s = 'Its a very good good idea' # \b是匹配一个单词的边界,这个正则仅仅可以匹配两个相同的单词连着的情况 # 先搜索到匹配的所有单词,然后用\1是引用第一个括号的内容,这就是分组的作用 # 解释一下这个正则表达式:他不是一次匹配一个good,而是直接匹配good good,然后有一个分组,所以第二个good直接就用的是\1,直接引用了第一个分组的内容 print(re.sub(r'(\b\w+) \1', r'\1', s)) #Its a very good idea # 注意两层括号嵌套 print(re.sub(r'((\w+) )\1', r'\2', s)) #Its a very goodidea
5.match函数。
有关search、findall、finditer三个方法的区别。参见下面这篇文章
python正则表达式精讲---search与findall | 酷python (coolpython.net)
s = '<html><head>This is head.</head><body>This is body.</body></html>' pattern = re.compile('<html><head>(?P<head>.*)</head><body>(?P<body>.*)</body></html>') re_match = re.match(pattern, s) print(re_match.group('head')) # This is head. print(re_match.group('body')) # This is body.
例:现有一段话,我们通过三种方法来提取其中的全部的电话号码。
import re telNumber = '''Suppose my Phone No. is 0551-1234567, yours is 010-12345678, his is 025-87654321.''' pattern = re.compile(r'((\d{3,4})-(\d{7,8}))') #1. match对象的search() #search返回的每次只是第一个匹配到的,若想继续匹配,应该缩小范围继续search,知道全部找完为止 match=pattern.search(telNumber) while match: print(match.group()) print(match.span()) match=pattern.search(telNumber,match.end()) #2. match对象的findall()方法,直接一下就能返回匹配到的全部的内容。 print(pattern.findall(telNumber)) #3. match对象的finditer()返回的是迭代器对象,必须通过group()来取出内容 print(pattern.finditer(telNumber)) for i in pattern.finditer(telNumber): print(i.groups())
example = 'why you dont love me,where is my fault?' pattern = re.compile(r'\Bn\w+\b') #查找所有不已经n开头,但是含有n的单词部分 print(pattern.search(example)) pattern = re.compile(r'\b\w*i\w*\b') #查找所有含i的单词 print(pattern.findall(example)) text = "Badasd basdasd" pattern = re.compile('\\bb\w+\\b') # pattern = re.compile(r'\bb\w+\b') 要么写两个\\,要么加r print(pattern.findall(text))
子模式。
m = re.match(r"(\d+)\.(\d+)", "24.1632") print(m.groups()) #返回所有的子模式匹配 ('24', '1632')
匹配模式标志的写法:
这种是老式的写法
这个是新式的写法。
pattern = re.compile(r'\bn\w+\b', re.I)
string = 'I want to eat a apple,eat two Apple' # 匹配前面没有a的apple,并且忽略的大小写 pattern = re.compile(r'(?<!a\s)apple\b', re.I) #['Apple'] print(pattern.findall(string))
例子:单词重复匹配检测
# 匹配有重复字母的单词 s = 'aabc abcd abbcd abccd abcdd' # 最外层没加括号 pattern = re.compile(r'\b\w*(?P<name>\w+)(?P=name)\w*\b') print(pattern.findall(s)) # ['a', 'b', 'c', 'd'] # 最外层加了括号 pattern = re.compile(r'(\b\w*(?P<f>\w+)(?P=f)\w*\b)') print(pattern.findall(s)) # [('aabc', 'a'), ('abbcd', 'b'), ('abccd', 'c'), ('abcdd', 'd')]