1 Introduction

1.1 Definity

  • 正则表达式: 描述文本规则的工具,记录文本规则的代码;
  • 通配符: 文本匹配工具,它非常简陋,一般只在文件名匹配中使用;

正则表达式的匹配流程:

  • 正则表达式引擎对pattern进行编译, 得到一个正则表达式对象
  • 使用正则表达式对象对需要进行匹配的原始文本进行匹配, 并输出匹配结果

关于正则表达式的匹配原理以及匹配引擎的工作机制不在本文章的讨论范围, 下文仅仅讲述
正则表达式的pattern语法, 本文章主要讲述python相关的正则表达式.

参考: python正则表达式指南

1.2 Glossary

  • 字符: 一般字符, ., \--转义, [...]--字符集
  • 预定义字符集: \d, \D, \s, \S, \w, \W, 可以放在字符集中
  • 数量词: *, +, ?, {m}, {m,n}, *?, +?, ??, {m,n}?, 一般放在字符以及(..)之后, 表示匹配的数量
  • 边界匹配: ^, $, \A, \Z, \b, \B, 仅作为边界匹配, 不会消耗原始字符串中的字符
  • 逻辑: |, 或关系
  • 分组: (..), (?P<name>..), \<number>, (?P=name), 分组, 可以对该分组定义别名, 之后可以访问该分组
  • 特殊结构: (?:..), (?iLmsux), (?#..), (?=..), (?!..), (?<=..), (?<!..)

1.3 Quick Guide

Reular Expressions Quick Reference Guide

2 边界值

不消耗原始字符串中的字符

2.1 词锚定

  • 词首:\< 或者 \b,例如\<abc表示以abc为首的单词
  • 词尾:\> 或者 \b,例如abc\>表示以abc为结尾的单词
  • 单词和非单词之间: \b, 单词边界, 本身不匹配任何字符, 等价于(?<!\w)(?=\w)|(?<=\w)(?!\w)
  • 单词边界取反: \B, 等价于[^\b]

单词边界一般用于在需要匹配某一个单词字符组成的子串, 但是这个字符不能包含在由单词字符组成的更长的子串中,
例如需要替换掉单词to, 那么today明显不在替换范围内, 则需要使用\bto\b来进行限定.

单词边界在HTML的标签匹配中常用, 用以区分相互包含的标签, 比如要过滤掉<b>, </b>, <p…>, <img…>等标签,
但要保留<br />, 则正则表达式如下: <(/?b|p|img)\b[^>]*>

另外, 在字符集中, \b表示退格键

2.2 行锚定

  • 行首:^,例如^@表示以@开始的所有行
  • 行尾:$,例如}$表示以}结尾的所有行

2.3 字符串锚定

  • 字符串开头: \A, 例如: \Ahead会匹配Head line, 不会匹配My Head
  • 字符串末尾: \Z

3 量词

3.1 常用限定符

1
2
3
4
5
6
*                    重复0+
+ 重复1+
? 重复0/1
{n} 重复n
{n,} 重复n+
{n,m} 重复n到m
  • 注意1:?的用法,这个很容易遗忘.
  • 注意2: for portability(可移植性), keep it between 0 and 255 inclusive(之间).

3.2 贪婪和非贪婪

对于上一节的所有量词, 都存在两个模式: 贪婪模式, 非贪婪模式, python默认为贪婪模式, 此模式下,
会尽可能的匹配更多的字符.

格式: *?, +?, ??, {m,n}?

4 字符

  • 一般字符: 匹配自身
  • .: 匹配任意除\n之外的字符
  • \: 转义字符
  • […]: 字符集, 匹配其中任意一个即可

5 预定义字符

  • \d: 数字[0-9]
  • \D: 非数字, 等同于[^0-9]
  • \x: 16进制数字, 等同于[0-9A-Fa-f]
  • \X: 16进制字符意外的其他任意字符
  • \t: 匹配TAB字符
  • \s: 空白字符, [ \t\r\n\f\v]
  • \S: 非空白字符
  • \w: 单词字符, [A-Za-z0-9_]
  • \W: 非单词字符

6 分组

6.1 匹配

  • 默认编号分组: (...), 每一个括号表达式都是一个分组, 但是未进行命名操作
  • 命名分组: (?P<name>...), 对该分组指定一个别名, 例如: (?P<id>abc){2}

6.2 引用

  • 非命名分组: 引用指定编号的分组, \<number>, 例如: (\d)abc\1
  • 命令分组: (?P=<name>), 例如: (?P<id>\d)abc(?P=id)

7 特殊结构

7.1 集合

不使用分组编号, 但是以一个集合概念对外呈现, (?:...), 以便可以对整个集合进行
或运算, 或者量词运算.

7.2 匹配模式

使用某些特殊字符表示指定的匹配模式, 格式: (?<PAT>),

  • i: 忽略大小写
  • L: 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
  • m: 多行模式, 更改了^/$的行为
  • s: 点任何匹配, 更改.的行为
  • u: 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
  • x: 详细模式, 可以以多行呈现模式, 并且可以增加注释, 忽略空格

详细模式介绍:

1
2
3
p1 = r"""\d+        # 数字
\. # xx
a"""

7.3 注释

对正则的注释, (?#...), 仅仅是为了让正则更加清晰, 例如: abc(?#注释)123

7.4 前后内容匹配

对指定方向的内容进行检查, 当且仅当指定范围的内容匹配之后才能匹配后续的模式

  • 之后的内容匹配: (?=...), 例如: a(?=\d)表示a的后面必须是数字
  • 之后的内容不匹配: (?!...)
  • 之前的内容匹配: (?<=...), 例如: (?<=\d)b表示a和b的中间必须为数字, 注意是b的前面的任意字符, 限定条件非常大
  • 之前的内容不匹配: (?<!...)

上述的前后内容不匹配一般很少用到, 因为其限制条件很大, 一般场景都不适合

7.5 组匹配

相当于if-else语法或者三目运算符, 格式: (?(id/name)yes-pattern|no-paatern).
如果指定分组已经匹配到相应值, 则后续必须匹配yes-pattern, 否则反之.

例如: (\d)abc(?(1)\d|abc) , 则会匹配: 1abc2, abcabc

8 python

8.1 Match

匹配成功后的对象, 其中各个属性的含义:

  • string: 匹配时使用的文本
  • re: 匹配时使用的Pattern对象
  • pos: 文本中正则表达式开始搜索的索引, 从哪里开始进行匹配工作
  • endpost:
  • lastindex: 最后一个被捕获的分组在文本中的索引, 如果未捕获, 则为none
  • lastgroup: 最后一个被捕获的分组别名

方法:

  • group([group1, …]): 获取一个或者多个分组截获的字符串, 其中可以使用编号或者别名, 例如: 0-代表整个匹配的子串
  • groups([default]): 以元祖形式返回所有分组截获的字符串
  • start([group]): 返回指定的组截获的子串在string中的起始索引, 默认为0
  • end([group])

8.2 Pattern

编译好的正则表达式对象, 其中

  • pattern: 编译时的正则
  • flags: 编译时的匹配模式
  • groups: 表达式中的分组数量
  • groupindex: 以表达式中有别名的组的别名为key, 以该组对应的编号为value, 组成一个字典

8.3 method

  • match: 从指定的pos/endpost范围进行匹配, 默认从0~end, 要求开头就必须匹配, 不一定要求结尾
  • search: 子串
  • findall: 搜索, 以列表形式返回
  • sub: 对每一个匹配的子串进行替换

9 Vim

vim下的正则表达式在表示数量的元字符可能有一些特殊

9.1 转义元字符

  • *: 匹配*字符
  • .: 匹配.字符
  • \/: 匹配/字符
  • \: 匹配\字符
  • [: 匹配[字符
  • ]: 匹配]字符

9.2 数量元字符

  • *: 匹配0~N个任意字符
  • +: 匹配1~N个任意字符
  • \?: 匹配0~1个任意字符
  • {n, m}: 匹配n~m个任意字符
  • {n}: 匹配n个任意字符
  • {n,}: 匹配n~N个任意字符
  • {,m}: 匹配0~m个任意字符

9.3 位置元字符

  • $: 匹配行尾
  • ^: 匹配行首
  • \<: 匹配单词词首
  • \>: 匹配单词词尾

9.4 替换变量

\(\)括起来的正则表达式,在后面使用的时候可以用\1, \2等变量来
访问\(\)中的内容.

vim中的整体简单替换表达式: [range]s/from/to/[flags], 其中flags的选项有四个值:

  • c: confirm, 每次替换前询问
  • e: error, 不显示错误信息
  • g: global, 不询问, 整行替换, 不仅仅替换首个字符
  • i: ignore, 忽略大小写