2023.10.31
之前只是知道有这么个东西,上学没好好学,之前工作也是边查边用,用完就忘。
最近空窗期备考华子刷题有用到,顺带整理和知识补足。
正则的东西有点多,从零开始理解,用到哪些就写到这来。
正则表达式,一个特殊的字符序列,用来描述一种模式,或者说成是规则。
然后可以对字符串进行操作,来判断字符串是否符合这种模式,
或者去查找字符串内是否包含满足这种模式的字符串,甚至进行替换。
正则表达式,这个序列的写法规则及对应的概念和意义:
字符集合设定: 用中括号括起 [abc123] 来表示其中任一字符
中划线 - :[a-zA-Z] 来表示 所有的大小写字母
非 ^ :[^a-zA-Z] 写在中括号内开头 表示除了中括号内的字符之外的任意字符
[a-z^A-Z] 写在其他地方,就只表示它本身而没有取非的意思
数字 \d : 等同于[0-9]
非数字 \D : 等同于[^0-9]
字母数字 \w : 等同于[a-zA-Z0-9]
非字母非数字 \W : 等同于[^a-zA-Z0-9]
重复:用以表示前面紧挨着的字符集合的次数
0+次 * : 表示0次或以上
1+次 + : 表示1次或以上
0,1次 ? : 表示0次或者1次, 要么0要么1
精确次数 {m,n}: 表示最少m次到最多n次之间
组: 用以表示正则序列内的一部分
用圆括号括起来 ( ) 即为一组
([a-zA-Z]+)(\d+) 这个正则序列内有两个组
组号0表示正则序列本身
组号1表示字母
组号2表示数组
正则的使用:
1. 第一题用到的是匹配(查找)
查找,在这里写两个方法,re.match() 和 re.search(),先看代码
import re
s = 'Seven77'
matcher = re.match(r'([a-zA-Z]+)(\d+)', s)
print(matcher) #
print(matcher.group(0)) # Seven77
print(matcher.group(1)) # Seven
print(matcher.group(2)) # 77
print(matcher.group(3)) # IndexError: no such group
import re
s = 'Seven77'
searcher = re.search(r'([a-zA-Z]+)(\d+)', s)
print(searcher) #
print(searcher.group(0)) # Seven77
print(searcher.group(1)) # Seven
print(searcher.group(2)) # 77
print(searcher.group(3)) # IndexError: no such group
两个方法都是查找匹配,并且可以用.group()来取到,匹配成功的部分对应的组内的值
区别见下例:
import re
s = '0Seven77'
matcher = re.match(r'([a-zA-Z]+)(\d+)', s)
print(matcher) # None
print(matcher.group(0)) # AttributeError: 'NoneType' object has no attribute 'group'
print(matcher.group(1)) # AttributeError: 'NoneType' object has no attribute 'group'
print(matcher.group(2)) # AttributeError: 'NoneType' object has no attribute 'group'
import re
s = '0Seven77'
searcher = re.search(r'([a-zA-Z]+)(\d+)', s)
print(searcher) #
print(searcher.group(0)) # Seven77
print(searcher.group(1)) # Seven
print(searcher.group(2)) # 77
两者查找匹配,都是从前往后,但区别在于,如果match一开始没有查到满足的字串,则返回None
而search则会尝试向后查找,若有则返回。若无则返回None。
import re
ss = '0Seven'
searcher = re.search(r'([a-zA-Z]+)(\d+)', ss)
print(searcher) # None
print(searcher.group(0)) # AttributeError: 'NoneType' object has no attribute 'group'
print(searcher.group(1)) # AttributeError: 'NoneType' object has no attribute 'group'
print(searcher.group(2)) # AttributeError: 'NoneType' object has no attribute 'group'
所以一般用完match()或者search()后,在取值之前要进行是否为None的判断。代码暂略。
知道这几块就可以解第一道报文重排序的题了。
==========================分割线=======================================
多带一嘴关于re.compile() 上代码
import re
s1 = 'eg11'
s2 = 'eg22'
s3 = 'eg33'
matcher1 = re.match(r'([a-zA-Z]+)(\d+)', s1)
matcher2 = re.match(r'([a-zA-Z]+)(\d+)', s2)
matcher3 = re.match(r'([a-zA-Z]+)(\d+)', s3)
此时正则被写了三次,虽说可以cv但还是有点麻烦,因此介入compile()
import re
s1 = 'eg11'
s2 = 'eg22'
s3 = 'eg33'
reg = re.compile(r'([a-zA-Z]+)(\d+)')
matcher1 = reg.match(s1)
matcher2 = reg.match(s2)
matcher3 = reg.match(s3)
两种写法完全等效,同样可以用于search()和其他方法
参考文章:
python | 史上最全的正则表达式_python 正则表达式-CSDN博客
华为OD机试 - 报文重排序(Java & JS & Python & C)-CSDN博客
==========================分割线=======================================
2023.11.08
遇到了正则替换,就再来写一下关于re.sub(),把匹配上的部分进行替换。
可以看一下参考那篇文章
简单说起就是要有三个参数,1.正则 2.替换成什么 3.原字符串
更高级的可以声明做几次替换, 以及是否忽略大小写什么的
先记最质朴的:
import re
s = '[10,20,5]'
ret = re.sub(r'[\[\]]', '', s)
print(ret) # 10,20,5
或者
import re
s = '[10,20,5]'
reg = re.compile(r'[\[\]]')
ret = reg.sub('', s)
print(ret) # 10,20,5
顺带一提,如果正则写的时候没写原样字符标识r, 会抛一个警告:
SyntaxWarning: invalid escape sequence '\['
是在提示当前代码中的反斜线 \ 被视为转义字符
使用正则时候大多都要写r的,不然有时会很迷糊
以上。
参考文章:
re.sub()用法详解_IT之一小佬的博客-CSDN博客
SyntaxWarning: invalid escape sequence ‘\p‘-CSDN博客
==========================分割线=======================================
2024.01.05 关于符号与贪婪
首先是字符点 '.' 用来匹配除 "\n" 之外的任何单个字符。
(要匹配包括 '\n' 在内的任何字符,请使用如 '[.\n]' 的模式)
(当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符)
(如果使用了 ’S’ 选项,匹配包括 ’/n’ 的所有字符。)
其次是字符 '*', '+', '?' 此三者用来表明重复次数
* 表示前置规则重复 0次或1次或多次
+ 表示前置规则重复 1次或多次
? 表示前置规则重复 0次或1次
+ 与 * 二者的后面,可以加 ? 来表示非贪婪
贪婪,顾名思义,尽可能多的
+ 本身,表示一次或多次匹配,在默认的贪婪模式下,会匹配尽可能多的字符
* 同理
这时引出, +? 表示一次或多次匹配,但是不贪婪,会匹配尽可能少的字符
*? 同理
下面的示例是搬运,先附原文链接,原作者写的太好了,连我都看懂了!
https://www.cnblogs.com/wjx-blog/p/12123279.html
1. .*
. 表示 匹配除换行符 \n 之外的任何单字符,*表示零次或多次。所以.*在一起就表示任意字符出现零次或多次。没有?表示贪婪模式。比如a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
又比如模式src=`.*`, 它将会匹配最长的以 src=` 开始,以`结束的最长的字符串。用它来搜索 时,将会返回 src=``test.jpg` width=`60px` height=`80px`2. .*?
?跟在*或者+后边用时,表示懒惰模式。也称非贪婪模式。就是匹配尽可能少的字符。就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。
a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。
又比如模式 src=`.*?`,它将会匹配 src=` 开始,以 ` 结束的尽可能短的字符串。且开始和结束中间可以没有字符,因为*表示零到多个。用它来搜索 时,将会返回 src=``。3. .+?
同上,?跟在*或者+后边用时,表示懒惰模式。也称非贪婪模式。就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。
a.+?b匹配最短的,以a开始,以b结束的字符串,但a和b中间至少要有一个字符。如果把它应用于ababccaab的话,它会匹配abab(第一到第四个字符)和aab(第七到第九个字符)。注意此时匹配结果不是ab,ab和aab。因为a和b中间至少要有一个字符。
又比如模式 src=`.+?`,它将会匹配 src=` 开始,以 ` 结束的尽可能短的字符串。且开始和结束中间必须有字符,因为+表示1到多个。用它来搜索 时,将会返回 src=``test.jpg`。注意与.*?时的区别,此时不会匹配src=``,因为src=` 和 ` 之间至少有一个字符。