沈阳网站建设哪里的公司比较好,如何自己建网站,狗头网网站,网站栏目定位python 正则使用详解什么是正则在 python 中使用正则一些正则的定义python 正则的方法match 从字符串开头匹配正则返回的结果分析#xff08;重要#xff09;fullmatch 严格匹配整个字符串search 任意位置开始匹配sub 替换匹配内容subn 以元组方式返回替换结果split 正则切割…
python 正则使用详解什么是正则在 python 中使用正则一些正则的定义python 正则的方法match 从字符串开头匹配正则返回的结果分析重要fullmatch 严格匹配整个字符串search 任意位置开始匹配sub 替换匹配内容subn 以元组方式返回替换结果split 正则切割findall 查找所有匹配结果finditer 返回一个迭代结果compile 正则表达式的预编译purge 清除缓存escape 正则表达式格式化什么是正则
正则很简单的哦不要因为看到和乱码差不多的样子就望而却步了他很有规律的。
简单来说就是用来描述字符串格式的比如数字就可以是 [0-9]也可以是 [0123456789]还可以是 \d
而日常我们使用正则则就是用这个描述格式来验证或匹配提取或批量替换用的比如 html 代码用 [^]*? 来匹配或删除所有标签
关于正则的入门知识可以围观一下老顾的文章《文盲的正则表达式入门》在这个文章里老顾以正则各种符号使用的场景用途做了区分和其他正则入门的教程不一样哦当然也没那么完整就是了。这个文章主要是用来方便理解正则的。
在 python 中使用正则
大部分的开发语言中都有对正则的支持毕竟这也是字符验证的一个主要流派了甚至不少数据库、命令行都有正则的支持比如 linux系统比如 mysql、oracle 数据库等所以正则还是有必要学一学的。
在 python 中正则的内容则放在 re 这个包里使用也很简单只要引用这个包就可以了
import re
print(re.findall(\d,123456 78/*9)) # 一个简单的例子找出字符串中所有数字在 python 的 re 包里他提供了不少的指令咱们来一一查看并学习为了不遗漏内容咱们把 re.py 这个文件打开照着这个文档的内容来进行。文件位置如图在 python 安装路径下的 lib 文件夹内。
一些正则的定义
在 re.py 这个文件中从第29行开始他简单的介绍了一些基本的特殊符号定义
The special characters are:
特殊字符为. Matches any character except a newline.匹配除换行符以外的任何字符。^ Matches the start of the string.匹配字符串的开头。$ Matches the end of the string or just before the newline at the end of the string.匹配字符串的末尾或位于的换行符之前新行的末端。* Matches 0 or more (greedy) repetitions of the preceding RE.Greedy means that it will match as many repetitions as possible.匹配0个或多个默认是贪婪模式由前边的正则片段定义的重复内容。贪婪模式意味着它会匹配尽可能多的重复。 Matches 1 or more (greedy) repetitions of the preceding RE.匹配1个或多个默认是贪婪模式由前边的正则片段定义的重复内容。? Matches 0 or 1 (greedy) of the preceding RE.匹配0个或1个默认是贪婪模式由前边的正则片段定义的内容。*?,?,?? Non-greedy versions of the previous three special characters.前边三个定义的非贪婪版本。老顾的正则入门里说过的哦*? 是长度定义在长度定义后加 ? 就表示非贪婪模式这个可以引用到任何长度定义中包括下边也有出现{m,n} Matches from m to n repetitions of the preceding RE.匹配至少 m 个最多 n 个由前边正则片段定义的内容。默认是贪婪模式{m,n}? Non-greedy version of the above.上边长度定义的非贪婪版本。\\ Either escapes special characters or signals a special sequence.要么转义特殊字符要么就是一个已经预定义的特殊序列。好吧老顾也不知道怎么准确翻译这里的特殊序列指的就是预定义的字符集比如\d表示数字\n表示回车[] Indicates a set of characters.A ^ as the first character indicates a complementing set.表示一组字符。也就是老顾说的字符集比如 \d 是已经预定义好的但是是全部数字也许我们只需要123不需要其他数字那么就必须自己定义字符集 [123] 这个样子作为第一个字符的“^”表示一个补集。在字符集定义中如果 ^ 是第一个字符则表示这个是个补集换个说法就是不包含之后定义的字符集的其他字符集比如 [^\d] 就是所有非数字的字符| A|B, creates an RE that will match either A or B.A|B创建一个匹配A或B的正则片段。(...) Matches the RE inside the parentheses.The contents can be retrieved or matched later in the string.匹配括号内的正则片段。稍后可以在字符串中检索或匹配内容。事实上除了稍后在其他地方使用在当前正则片段后的部分也可以使用(?aiLmsux) The letters set the corresponding flags defined below.字母设置下面定义的相应标志。这个用法老顾还没试过翻译为百度翻译的结果(?:...) Non-grouping version of regular parentheses.正则圆括号的非分组版本。也就是不可引用、追溯的部分(?Pname...) The substring matched by the group is accessible by name.组匹配的子字符串可以通过名称访问。给分组定个名字然后通过名字访问(?Pname) Matches the text matched earlier by the group named name.匹配前面由组名称匹配的文本。(?#...) A comment; ignored.一个注释忽略掉。嗯我讨厌写注释(?...) Matches if ... matches next, but doesnt consume the string.右断言位置修饰如果能匹配成功则匹配之后的正则片段该修饰不占用匹配空间。(?!...) Matches if ... doesnt match next.右断言与上一个修饰意思相反如果不符合之后的正则片段则继续匹配。(?...) Matches if preceded by ... (must be fixed length).左断言如果前边的字符符合正则片段...必须定长(?!...) Matches if not preceded by ... (must be fixed length).左断言如果前边的字符不符合正则片段...必须定长(?(id/name)yes|no) Matches yes pattern if the group with id/name matched, the (optional) no pattern otherwise.如果具有id/name的组匹配则匹配yes模式否则为可选无模式。同样没用过的方法通过这个内容我们基本就可以确定 python 中正则能完成哪些描述这样的描述又有什么样的限制了。
再之后从62 行开始还介绍了一些预定义字符集这里就不翻译了大家随便看看就好基本都差不多。
再然后87 行开始说明了 re 这个包之中包含的各种方法嗯之后一一讲解
以及102行开始的正则修饰。。。。老顾最常用的就是忽略大小写修饰这个修饰是在正则定义之外的还有多行匹配也偶尔用用其他的说实话老顾基本用不上。
python 正则的方法
约定之后的所有内容默认都已经引入了 re 包即代码中已经包含了 import re
match 从字符串开头匹配 Match a regular expression pattern to the beginning of a string. 将正则表达式模式与字符串的开头匹配。 语法 match(pattern, string, flags0) match(正则表达式,匹配字符串,正则表达式修饰(默认为0)) 需要注意这个方法时严格从字符串开头进行匹配的如果想在字符串中间找到匹配不要用这个方法哦。
示例
print(re.match(\d,123.548))
# 返回结果
re.Match object; span(0, 3), match123
print(re.match(\s\d,123.548))
# 返回结果匹配失败没有Match信息
None在python中使用匹配返回的结果大部分都是 re.Match 对象他包含了一个 span 元组这个元组就是匹配字符串对应的切片位置match 就是匹配的结果了
正则返回的结果分析重要
ans re.match(\d,123.548)
print(ans)
re.Match object; span(0, 3), match123我们通过一个变量来分析返回的结果该如何使用
print(ans.re) # 输出这个匹配的正则
re.compile(\\d) # 包含了我们正则片段的正则编译对象
print(ans.string) # 输出这个匹配的原始匹配字符串
123.548
print(ans.pos,ans.endpos) # 输出原始字符串的切片包括起始位置和结束位置
0 7
print(ans.regs) # 输出匹配的结果注意这里是元组每一个内层元组是一个匹配
((0, 3),)
print(ans.span) # 输出span方法
built-in method span of re.Match object at 0x00000148614E76C0
print(ans.span(0)) # 输出第一个匹配的切片信息
(0, 3)
print(ans.start(0),ans.end(0)) # 返回指定匹配顺序的切片开始和结束位置
0 3
print(ans.group(0)) # 返回第一个匹配结果匹配到的内容
123嗯由于刚才的匹配我们简单的匹配了一个 \d没有带分组信息这次我们加上一个分组来尝试
ans re.match((\d)\.(\d),123.548) # 带有两个分组的正则匹配
print(ans)
re.Match object; span(0, 7), match123.548
print(ans.span(0),ans.span(1),ans.span(2)) # 返回所有的切片信息
#这里需要注意的是如果带有分组那么原始字符串自动占据返回结果的第一个分组即下标为0的分组
#所以实时上我们需要提取的结果应该是从下标1开始的
(0, 7) (0, 3) (4, 7)
print(ans.group(0),ans.group(1),ans.group(2)) # 输出该匹配结果的分组结果
123.548 123 548
print(ans.groups()) # 输出该匹配的分组内容注意这里的groups没有参数输入参数也是无效的
# 所以想要引用结果必须使用 group
(123, 548)
print(ans.groups(101))
(123, 548)
print(ans.expand(\\1 is \\2)) # 将匹配结果按照指定的字符串格式输出这里可以引用分组结果
123 is 548好了经过这几个输出我们应该明白了正则匹配结果返回的内容都包含哪些信息了还有个别的属性方法老顾也不太清楚这里就不再讲解了
有了这些方法和属性我们就可以很方便的使用正则返回结果中的内容了
fullmatch 严格匹配整个字符串 Match a regular expression pattern to all of a string. 将正则表达式模式与所有字符串匹配。 语法 fullmatch(pattern, string, flags0) fullmatch(正则表达式,匹配字符串,正则表达式修饰(默认为0)) print(re.fullmatch([a-z],0123456)) # 由于没有字母匹配失败
None
print(re.fullmatch([a-z],Abcd efgh,re.IGNORECASE)) # 虽然忽略大小写了但是中间有空格不能严格匹配匹配失败
None
print(re.fullmatch(\d,0123456)) # 整个字符串严格匹配 \d
re.Match object; span(0, 7), match0123456
print(re.fullmatch([a-z],Abcdefgh,re.IGNORECASE)) # 整个字符串严格匹配 [a-z]
re.Match object; span(0, 8), matchAbcdefgh
print(re.fullmatch([a-z],Abcdefgh,re.IGNORECASE)) # 长度对应不上没有长度修饰则只匹配一个字符的字符串才可以成功
None嗯就是严格匹配字符串首尾默认相当于 search 的正则前边带 ^ 后边带 $
search 任意位置开始匹配 Search a string for the presence of a pattern. 在字符串中搜索是否存在模式。 语法 search(pattern, string, flags0) search(正则表达式,匹配字符串,正则表达式修饰(默认为0)) print(re.search([a-z],0123456)) # 没有匹配到结果返回 None
None
print(re.search([a-z],Abcd efgh,re.IGNORECASE)) # 返回第一个匹配成功的结果片段
re.Match object; span(0, 4), matchAbcd
print(re.search(\d,abcde0123456)) # 返回第一个匹配成功的结果片段
re.Match object; span(5, 12), match0123456
print(re.search([a-z],Abcdefgh,re.IGNORECASE)) # 整个字符串都符合正则所以完整返回了
re.Match object; span(0, 8), matchAbcdefgh
print(re.search([a-z],Abcdefgh,re.IGNORECASE)) # 返回第一个匹配成功的片段
re.Match object; span(0, 1), matchA很明显search 要比 match 和 fullmatch 要宽松很多我们可以更自由的发挥
sub 替换匹配内容 Substitute occurrences of a pattern found in a string. 替换字符串中发现的模式的出现次数。百度翻译的什么鬼 替换字符串中所有或指定次数的符合匹配的内容。老顾翻译 语法 sub(pattern, repl, string, count0, flags0) sub(正则表达式,替换表达式,匹配字符串,替换次数,正则表达式修饰(默认为0)) print(re.sub((\d{2}),\\1-,18300183000)) # 将数字每两位之后加一个减号
18-30-01-83-00-0
----
print(re.sub((?\d)(?!\d),\n,1开始2结束3运行4调试11开会12报告)) # 在每个连续数字前插入一个换行大家可以和下一个比较一下有什么不同1开始
2结束
3运行
4调试
11开会
12报告
----
print(re.sub((?\d),\n,1开始2结束3运行4调试11开会12报告)) # 在每个数字前插入一个换行1开始
2结束
3运行
4调试
1
1开会
1
2报告
----
print(re.sub((?\d)(?!\d),\n,1开始2结束3运行4调试11开会12报告,count5)) # 指定了替换次数的正则替换1开始
2结束
3运行
4调试
11开会12报告正则替换还是很好用的但是这里要说一个但是python 的正则替换里描述的内容有一个很重要的部分很多人可能都忽略掉了。原文如下
def sub(pattern, repl, string, count0, flags0):Return the string obtained by replacing the leftmostnon-overlapping occurrences of the pattern in string by thereplacement repl. repl can be either a string or a callable;if a string, backslash escapes in it are processed. If it isa callable, its passed the Match object and must returna replacement string to be used.return _compile(pattern, flags).sub(repl, string, count)repl can be either a string or a callable; repl可以是字符串也可以是可调用的 If it is a callable, it’s passed the Match object and must return a replacement string to be used. 如果是可调用的的话它传递Match对象并且必须返回要使用的替换字符串。 也就是说我可以通过委托的方法来处理匹配到的内容并返回指定的结果 来我们试试看哦
def star(n): # 这里的 n 就是一个正则匹配对象Matchreturn * * int(n.group(0)) \n # 将匹配到的数字转成星星的数量并返回星星print(re.sub(\d,star,123456789)) # 委托匹配到的内容使用 star 方法来处理
*
**
***
****
*****
******
*******
********
*********import random
def star(n):return .join([random.choice(abcdefghijklmnopqrstuvwxyz) for _ in range(int(n.group(0)))]) \nprint(re.sub(\d,star,123454321))
v
sr
lvd
trtm
rnhrq
loxb
vjd
su
i以及老顾在《在学习爬虫的路上有多少坑在前边》一文中实际用到的两个转编码的函数
正则替换如此强大你还不心动吗
subn 以元组方式返回替换结果 Same as sub, but also return the number of substitutions made. 与sub相同但也返回进行的替换次数。百度翻译持续不说人话 和 sub 方法一样但是在元组中记录了替换的次数。老顾翻译 语法 subn(pattern, repl, string, count0, flags0) subn(正则表达式,替换表达式,匹配字符串,替换次数,正则表达式修饰(默认为0)) print(re.subn((?\d)(?!\d),\n,1开始2结束3运行4调试11开会12报告))
(\n1开始\n2结束\n3运行\n4调试\n11开会\n12报告, 6) # 元组第一个元素为返回结果第二个元素为替换次数def star(n):return * * int(n.group(0)) \nprint(re.subn(\d,star,13243546576879))
(*\n***\n**\n****\n***\n*****\n****\n******\n*****\n*******\n******\n********\n*******\n*********\n, 14)subn 就不细说了和sub一样的玩法
split 正则切割 Split a string by the occurrences of a pattern. 按出现的模式拆分字符串。 语法 split(pattern, string, maxsplit0, flags0) split(正则表达式,匹配字符串,最大切割次数(默认0即不限制次数),正则表达式修饰(默认为0)) print(re.split([^\d],13 243,54uu6576879)) # 以非数字的字符为切割符切割字符串
[13, 243, 54, , 6576879] # 由于两个 u 之间没有数字所以结果中会出现空字符串print(re.split([^\d],13 243,54uu6576879,maxsplit2)) # 指定最大切割次数的分割字符串
[13, 243, 54uu6576879]嗯。。。。很常用实用以及很容易用不细说了
需要注意的是这里返回的就是字符串数组没有Match信息了
findall 查找所有匹配结果 Find all occurrences of a pattern in a string. 查找字符串中出现的所有模式。 语法 findall(pattern, string, flags0) findall(正则表达式,匹配字符串,正则表达式修饰(默认为0)) 额。。。怎么说呢在抛弃了Match信息的情况下以字符串数组方式返回所有匹配
print(re.findall(\d,13 243,54uu6576879))
[13, 243, 54, 6576879]在大部分的工作中其实这个也就够用了因为我们并不关心他出现在什么地方前后文有什么但在一些需求比较复杂的时候这个 findall 就不如 finditer 了因为 findall 丢失了Match信息而finditer还保留着Match信息
finditer 返回一个迭代结果 Return an iterator yielding a Match object for each match. 返回一个迭代器为每个匹配生成一个Match对象。 语法 finditer(pattern, string, flags0) finditer(正则表达式,匹配字符串,正则表达式修饰(默认为0)) print(re.finditer(\d,13 243,54uu6576879)) # 返回了一个迭代器
callable_iterator object at 0x00000148615CD540for m in re.finditer(\d,13 243,54uu6576879): #使用迭代将所有匹配输出print(m)
re.Match object; span(0, 2), match13 # 第一个匹配
re.Match object; span(3, 6), match243 # 第二个匹配
re.Match object; span(7, 9), match54 # 第三个匹配
re.Match object; span(11, 18), match6576879 # 第四个匹配由于这里完整的保留了Match的信息所以我们可以对匹配到的结果进行定位以及检查前后文之类的操作需要用的人自然会用到也就不细说了
compile 正则表达式的预编译 Compile a pattern into a Pattern object. 将模式编译为pattern对象。 语法 compile(pattern, flags0) 嗯。。。定义一个正则也许复杂的正则会用到这个老顾一般都直接写正则片段除了上了1k的正则老顾一般不会用这个
purge 清除缓存 Clear the regular expression cache. 清除正则表达式缓存。 语法 purge() 没啥用这是针对预编译的正则来说的老顾基本上都是随手写正则随手用没有预编译过
escape 正则表达式格式化 Backslash all non-alphanumerics in a string. 对正则表达式字符串中的所有非字母数字进行转义。 语法 escape(pattern) 这个还算有点用算是正则格式化的部分比如我们想从字符串中提取到一部分作为匹配内容但是匹配到的内容可能会有特殊符号比如*号?号之类的这些在正则中有其他意义所以我们需要提前将这些符号转义escape就是干这个用的将特殊符号都转义。老顾在 c# 中使用正则还单独自己写了个FormatRegex 方法就是干这个用的。郁闷。
print(re.escape(123.456*789$100)) # 格式化正则片段将其特殊符号都进行转义
123\.456\*789\$100