「Python」 Py正则表达式学习笔记

Posted by Dawn-K's Blog on May 20, 2020

Python正则表达式学习

Python语法

对于Python来说, 正则表达式是一个自带的强大的工具

匹配

re.match()

这个工具的目的其实是查看给定的母串存不存在一个前缀满足给定的规则. 也就是这个函数一定是从开头开始匹配母串的, 如果开头无法匹配, 则直接返回None

re.search()

使用方法和match一样, 不过是对整个母串进行匹配, 也就是查看母串有没有一个子串符合匹配

注意, 以上两个都只会匹配一次, 下面的两个是匹配多次

re.findall()

在字符串中找到正则表达式所匹配的所有子串, 并返回一个列表, 如果没有找到匹配的, 则返回空列表.

re.finditer()

和findall使用方法一样, 只是返回的是迭代器

1
2
3
test = re_tel.finditer('ppython')
for i in test:
    print(i.group())

举个例子

规则: py

母串: ppython 这是可以search的, 因为母串存在子串 py 能够满足规则, 但是使用match就会得到空

查找和替换

Python 的 re 模块提供了re.sub用于替换字符串中的匹配项.

语法:

re.sub(pattern, repl, string, count=0, flags=0)

参数:

pattern : 正则中的模式字符串。

repl : 替换的字符串,也可为一个函数。

string : 要被查找替换的原始字符串。

count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

1
2
after = re.sub(r'(\d{4})-(?:0?[1-9]|1[0-2])-(3[01]|[12][0-9]|0?[1-9])', '$data', 'gg2018-12-09') # 或许不在括号内的减号不用转义?
print(after) # gg$data
1
2
3
4
5
6
import re # 导入包
# 匹配整数或者小数
word = r'^[+\-]?\d+(\.\d+)?$'
# 日期,考虑到月份和日期的合法性
word = r'^\d{4}\-(0?[1-9]|1[0-2])\-(3[01]|[12][0-9]|0?[1-9])$'
test = re.match(word, '2018-02-6')

正则语法

符号 模式
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配任意字符,除了换行符.当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式
re+ 匹配1个或多个的表达式
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{n} 精确匹配n个前面的表达式
re{n,m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式.如果n缺省,则是[0..m],如果m缺省,则是至少n,最多无上限 . "o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*"。
a|b 匹配a或b
\w 匹配字母数字及下划线
\d 匹配任意数字,等价于 [0-9]
\s 匹配任意空白字符(包括回车),等价于 [\t\n\r\f]
\- 匹配减号
\. 匹配小数点
(re) 对正则表达式分组并记住匹配的文本
(?: re) 非捕获组,类似 (...), 但是不表示一个组
[\u4e00-\u9fa5] 匹配中文字符的正则表达式:

此外, 正则表达式自带的split, 比自带的有更强大的作用. 比如

1
2
3
4
5
ss = 'a b   c'.split(' ')        # ['a', 'b', '', '', 'c']
sss = re.split(r'\s+', 'a b  c') # ['a', 'b', 'c']

# 实际上自带的也能达到这个效果
s4 = list(filter(None, 'a b   c'.split(' '))) # ['a', 'b', 'c']

分组

使用括号的形式, 可以对正则表达式匹配后进行分组

在左括号的右侧加上 ?: 就可以使得括号失去分组的效果(注意后序的标号也会相应前移)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 日期,考虑到月份和日期的合法性
word = r'^(\d{4})\-(0?[1-9]|1[0-2])\-(3[01]|[12][0-9]|0?[1-9])$'
test = re.match(word, '2018-12-06')
print(test.group(0))
print(test.group(1))
print(test.group(2))
print(test.group(3))
print(test.groups())
# 2018-12-06   # group(0)默认为匹配的字符
# 2018         # 第一组
# 12           # 第二组
# 06           # 第三组
# ('2018', '12', '06')  # groups输出结果

贪婪匹配

正则表达式默认是贪婪匹配, 即在匹配的情况下默认匹配尽可能多的字符

*、+限定符都是贪婪的, 只有在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配.

转义问题

Python中的 [] 是一个神奇的操作, 在里面的绝大多数操作符都会变成原来的字面意思, 但是有五个操作符存在例外

- : - 位于 [] 内部的开头时表示其字面意思, 在内部则表示范围( [a-z] )等, 建议在使用其字面意思时, 无论其在哪都强制转义, 增强可读性.

^ : ^ 位于 [] 内部的开头时表示’非’, 但是在其他地方就表达字面意思. 也是建议使用字面意思时强制转义.

\[ , ] : 这三个字符由于非常常用, 所以在使用时一般都是字面意思强制转义.

编译

1
2
re_tel = re.compile(word) # 编译之后可以重复多次利用,在多次使用Match的时候可以提高速度
test = re_tel.match('pypython')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(?imx) 正则表达式包含三种可选标志:i, m,  x 。只影响括号中的区域。
(?-imx)	正则表达式关闭 i, m,  x 可选标志。只影响括号中的区域。
(?imx: re)	在括号中使用i, m,  x 可选标志
(?-imx: re)	在括号中不使用i, m,  x 可选标志
(?#...)	注释.
(?= re)	前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)	前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re)	匹配的独立模式,省去回溯。
\W	匹配非字母数字及下划线
\S	匹配任意非空字符
\D	匹配任意非数字
\A	匹配字符串开始
\Z	匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z	匹配字符串结束
\G	匹配最后匹配完成的位置。
\b	匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B	匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, .	匹配一个换行符。匹配一个制表符。
\1...\9	匹配第n个分组的内容。
\10	匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。