正则表达式 右上角加号_最全正则表达式讲解实战,附源码,敲一遍学会

ae9f57591404dc8ffa7cf40fa7e0cf00.pngcb20fe74e8cb86284e99be052ec16197.png

文章来源:王的机器

作者:王圣元

本文含 10026  字, 27  图表截屏 建议阅读  42  分钟 在公众号对话框回复  RE   获取完整 Jupyter Notebook0引言

正则表达式(Regular Expression, RE)就是一组定义某种搜索模式(pattern)的字符。

最简单的 RE 例子如下。

'steven'

很明显,这样一个 RE 只能搜索出含 steven 的字符串。

你可以用 Python 代码来验证,但现在假设我们还不会写,我们可以去 https://regex101.com/ 来验证。如下图右上角所示,匹配成功。

4a8b4b1bf628c60e10d217c488e21fe6.png

这样来搜索未免太傻了,有没有稍微智能一点的方法。再看下面的 RE。

^s....n$

上面的 RE 定义的模式如下:任何 6 个字符的单词,以 s 开头 (^s 的效果),以 n 收尾 (n$ 的效果)。之所以是 6 个字符,是因为有 4 个点 (.) 加上 s 和 n 字符。用上面那个网站做验证,这个 RE ^s....n$ 的若干匹配结果如下:

  • seven:不匹配(五个字母)

  • strong man:不匹配(十个字母加空格)

  • soften:匹配

  • steven:匹配

  • Steven:不匹配

看最后两个 steven 和 Steven,区别是第一个字母的大小写,如果我想匹配两者怎么办呢?用下面的 RE

^[s|S]....n$

中括号 [] 表示一个集合,而 | 分隔集合里面的元素,在本例是 s 和 S。意思就是匹配开头的 s 或 S,结尾是 n 的 6 字符的单词。 

44de488bd6ec610d5399a94a7175a00d.png

4a17ce92757f8f75e51f83018846c1ab.png

这样每次固定单词长度也不太智能吧(比如长度为 n 就需要手动输入 n 个点 .),开头 s 结尾 n 的单词好多呢,我如果都想搜索出来该怎么办呢?看下面的 RE

^s[a-z]+n$

现在 sun 和 strengthen 都可以匹配出来了。起作用的是 [a-z]+,[a-z] 表示小写的字母 a 到 z 的集合,而 + 代表大于一次,联合在一起的意思就是该单词“以 s 开头,以 n 结尾,中间有大于一个的任何小写字母”。

91fa506e6abd962f957efda0b4cd8d76.png

07b612fd1fced584c4880b91b91354b3.png

但上述模式对单词 self-restrain 不起作用,因为有个短连接线(hyphen)。

d5ac3f9b2fef34e211501da805e561ad.png

没关系,我们把 - 加入字母集合里,写成 [a-z-]+,注意第一个 - 表示从 a 到 z,第二个 - 表示短连接线。现在可以匹配 self-restrain 了。

821570193572c056d46fd0d09a62d327.png

目前对 RE 有点感觉了吧,即便不会确切的表示也没关系,因为这就是本帖要介绍的。还是那句话,兴趣最重要,有兴趣才能有效的往下看。

本帖结构如下:

  1. 原始字符串

  2. 五类元字符

  3. 七个函数

  4. 三个实例

注:本帖里的 RE 可视化可参考链接 https://www.debuggex.com/。

1原始字符串

原始字符串(raw string)是所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符,通常简称为 r-string。

如果没有转义字符,原始字符串和普通字符串是一样的,比如

print('hello')print(r'hello')
hello
hello

如果有转义字符(用反斜线 \),原始字符串和普通字符串是不一样的,比如

print('\blake')print(r'\blake')
lake
\blake

因此,不管什么时候用原始字符串准没错。

2元字符

元字符(meta character)就是一种自带特殊含义的字符,也叫特殊字符。比如 [] * + ? {} | () . ^ $ \,原字符按用途可分五类:

  • 表示集合:[]

  • 表示次数:* + ? {}

  • 表示并列:|

  • 用于提取:()

  • 用于转义:. ^ $ \

首先定义一个函数,当在句子(是个字符串 str)没有发现模式 pat 时,返回“没有找到”,反之打印出所有符合模式的子字符串。

import redef look_for(pat, str):    return '没有找到' if re.search(pat, str) is None                       else re.findall(pat, str)

上面代码中的 re 是 Python 中正则表达式的库,而 search 和 findall 是包里的两个函数,顾名思义它们做的就是搜索找出全部的意思,第三节会详解讲。

2.1

集合字符

中括号(square bracket)- []

中括号表示一个字符集,即创建的模式匹配中括号里指定字符集中的任意一个字符,字符集有三种方式来表现:

  • 明确字符:[abc] 会匹配字符 a,b 或者 c

  • 范围字符:[a-z] 会匹配字符 a 到 z

  • 补集字符:[^6] 会匹配除了 6 以外的字符

下面我们来一一细看。

明确字符

匹配中括号里面的任意一个字符。

pat = r'[abc]'
print( look_for(pat, 'a') )print( look_for(pat, 'ac') )print( look_for(pat, 'cba') )print( look_for(pat, 'steven') )
['a']
['a', 'c']
['c', 'b', 'a']
没有找到

分析如下:

该模式只匹配字符 a,b 或者 c,因此前三个例子的字符串里都有相应字符匹配,而最后例子里的 steven 不包含 a, b 或 c。

模式 [abc]  的可视图如下,注意 “One of” 是说集合里面的字符是“或”的关系。

df8950617c9f2eab89c0c413ce2b9ad7.png


范围字符

在 [ ] 中加入 - 即可设定范围,比如

  • [a-e] = [abcde]

  • [1-4] = [1234]

  • [a-ep] = [abcdep]

  • [0-38] = [01238]

看两个例子。

print( look_for(r'[a-ep]', 'person') )print( look_for(r'[0-38]', '666') )
['p', 'e']
没有找到

分析如下:

  • 例一的模式等价于 [abcdep],匹配单词 person 里面的 p 和 e 字符。

  • 例二的模式等价于 [01238],不匹配单词 666 里面的任何字符。

模式 [a-ep] 和 [0-38] 的可视图如下。

91c31a9f8c2311feceaebd680b0b2984.png

b0342c49bf6bc30b356eba83cde872a7.png


补集字符

在 [ ] 中加入 ^ 即可除去后面的字符集,比如

  • [^abc] 就是非 a, b, c 的字符

  • [^123] 就是非 1, 2, 3 的字符

看四个例子。

print( look_for(r'[^abc]', 'baba') )print( look_for(r'[^abc]', 'steven') )print( look_for(r'[^123]', '456') )print( look_for(r'[^123]', '1+2=3') )
没有找到
['s', 't', 'e', 'v', 'e', 'n']
['4', '5', '6']
['+', '=']

分析如下:

  • 例一 baba 里面所有字母不是 a 就是 b,因此没有匹配

  • 例二 steven 所有字母都不是 a, b 和 c,因此全部匹配

  • 例三 456 所有字母不是 1,2 和 3,因此全部匹配

  • 例四 1+2=3 有 +号=号不是 1, 2 和 3,因此它俩匹配

模式 [^abc] 和 [^123] 的可视图如下。注意 “None of” 是说集合里面的字符是的补集。

65908cc76511a44d6d47297a93a6204b.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值