python re 函数操作练习
Python Regexp 函数方法
3. re 模块操作
- re 模块的使用过程
4. 匹配单个字符
正则表达式的单字符匹配
字符 | 功能 |
---|---|
. | 匹配任意 1 个字符(除了) |
[ ] | 匹配[ ]中列举的字符 |
匹配数字,即 0-9 | |
匹配非数字,即不是数字 | |
匹配空白,即空格,tab 键 | |
匹配非空白 | |
匹配单词字符,即 az、AZ、0-9、_ | |
匹配非单词字符 |
- 点
.
匹配任意一个字符
配单个数字
[12345678] 匹配 1-8 中任意一个数字
[138] 匹配 1、3、8 中任意一个数字
[1-8] 同上
[1-36-8] s 匹配 1-3 或 6-8
1 | In [17]: re.match(r'速度与激情[12345678]','速度与激情4') |
[1-8abcd] 匹配数字 1-8 以及 a、b、c、d 四个字符
[1-8a-d] 匹配数字 1-8 以及 a-d
[1-8a-zA-Z] 匹配数字 1-8 以及 a-z 以及 A-Z
1 | In [33]: re.match(r'速度与激情[1-8abcd]','速度与激情7') |
配一个数字
匹配一个 word,其中包括:a-z, A-Z,0-9 还有下划线(_), 此外,它还能匹配中文。所以一般不使用它,使用[a-zA-Z0-9_] 来代替它
匹配一个空白字符,如:空格、 等
所有的大写字母都是匹配与小写相反的字符。
1 | In [43]: re.match(r'速度与激情\w','速度与激情5') |
5. 匹配多个字符
字符 | 功能 |
---|---|
* | 匹配前一个字符出现 0 次或者无限次,即可有可无 |
+ | 匹配前一个字符出现 1 次或者无限次,即至少有 1 次 |
? | 匹配前一个字符出现 1 次或者 0 次,即要么有 1 次,要么没有 |
{m} | 匹配前一个字符出现 m 次 |
{m,n} | 匹配前一个字符出现从 m 到 n 次 |
最简单的思路:多写几个单个字符匹配就成了多个字符匹配。
缺点:只能匹配指定个数的字符,多了少了都会报错。
1 | In [12]: re.match(r'速度与激情\d\d', '速度与激情45').group() |
使用大括号来限制前面的单个字符有多少个。
匹配 1 到 8 位数字,至少匹配 1 个数字,至多匹配 4 个数字
匹配 11 个连续的数字,中间不能有别的字符。
g{1,3} 匹配至少 1 个,至多 2 个字符 g
1 | In [15]: re.match(r'速度与激情\d{1,2}', '速度与激情3').group() |
? 前面的字符出现一次或零次
1 | In [33]: re.match(r'021-?\d{8}', '021-12345678').group() |
注意:三个双引号是字符串,放在函数下面,可以当作函数的说明。放到类的下面,可以看作是类的说明。
要想匹配所有字符,包括 ,可以使用
1 | In [52]: re.match(r'.*',html_content,re.S).group() |
单独使用 .*
只能匹配单行所有字符(有无),一旦遇到换行符就停止匹配了。可以加一个参数
re.S
+ 与 * 的区别: 前者不能匹配 空字符,后者可以匹配空字符
6. 位置锚定
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
配一个单词边界,也就是指单词和空格间的位置。 例如,“er可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。 匹配非单词边界。“ 例如:er”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
为什么不写^ 也能匹配开头,因为 python 的 match 函数**自动**从开头开始匹配,但是不会默认自动匹配到结尾。但是其他语言的函数不一定这样做。所以如果想要匹配整个字符串的还,一般开头写上 ^, 结尾写上 $
比如:判断变量名是否有效 问题中,以下代码就不能判断类似:‘a#ss’ 等在中间出现不正常字符的变量名
1 | ret = re.match(r'[a-zA-Z_][\w]*', name) |
改成:
1 | ret = re.match(r'^[a-zA-Z_][\w]*$', name) |
练习:匹配 4-13 个前缀(字母数字下划线)并以@163.com 结尾的邮箱,正则为:
1 | ret = re.match(r'^[a-zA-Z0-9_]{4,20}@163\.com$', mail) |
⚠️ 注意:
- 如果要全字符串匹配,不要忘记在最后使用 $ 符号
- 如果要在字符串中匹配那些正则表达式用到的字符,需要使用反斜杠进行转义。
7. 匹配分组
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num |
引用分组 num 匹配到的字符串 |
(?P) |
分组起别名 |
(?P=name) | 引用别名为 name 分组匹配到的字符串 |
小括号有两个功能:
分组匹配
单独取出小括号中的值
想要取某个位置的值,就给它加个括号。想要取第 n 个括号里面的东西,就用 group(n).
如果括号的个数为 m,你用 group(m+1) 会引发异常。
注意:测试过程中为了简洁起见,有时会使用 re.match().group() 这样的写法。正常开发代码的时候,需要分开写。因为前者会产生异常。
对上次写的匹配邮箱的正则进行改进,匹配多种邮箱:
1 | ret = re.match(r'^[a-zA-Z0-9_]{4,20}@(qq|outlook|163|gmail|126)\.com$', mail) |
注意:如果不写括号,那程序会默认将 | 前后的两大部分看成两个分组,而这并不是我们想要的。
分组的另一个应用:
判断 html_str = "<h1>hello wrold</h1>
"
中开闭标签是否配对
1 | re.match(r'<(\w*)>.*</\1>',html_str) |
因为想取某个位置的值,所以给他加上分组 (),
然后后面使用的时候,看他是第几个分组,就用 \几
1 | In [9]: html_str='<body><h1>hello</h1></body>' |
或者当分组过多时,数数并不方面,可以使用别名:
1 | In [17]: re.match(r'<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>',html_str) |
8. re 模块的高级用法
上面的大部分正则知识,在其他语言中基本都有。而这一节 ‘re 模块的高级用法’是 python 特有的,其他的语言可能没有。
8.1. search()
match() 是默认要求从头开始匹配,而 search 不是,它只是匹配字串中第一次出现符合正则匹配项的内容。
1 | In [28]: re.search(r"\d+","阅读次数:7887, 点赞数:454").group() |
当然,在 search 的正则中加上 ^,就和 match 一样了。
8.2. findall()
search 是只匹配符合正则的第一个字串,而 findall 是返回所有匹配正则的数据,返回值为列表。
一般在网页批量获取特定格式的数据时,经常使用它
⚠️:获取 findall 的返回结果不需要使用 group()
1 | In [73]: re.findall(r'\d+','python = 999, c = 22,c++ = 1212') |
8.3. sub()
- 将正则表达式匹配到的数据,替换为你输入的参数值
- 支持函数调用
匹配替换:
1 | In [74]: re.sub(r'\d+','hello','python = 999, c = 22,c++ = 1212') |
函数调用:
匹配到符合条件的字串时,自动调用函数。将正则匹配的返回对象传到函数中。并接受该函数的返回值来替换匹配到的东西。
8.4. split()
根据匹配进行切割字符串,并返回一个列表。
练习:将冒号或空格作为分隔符,分割字符串:“info:xiaoZhang 33 shandong”
1 | import re |
https://www.jianshu.com/p/9860f951616e
look ahead look behind
常常用于计数: Find a string
1 | import re |
当然,此题目更适合用简单遍历匹配解决:
1 | def count_substring(string, sub_string): |