正则表达式
学习如何使用正则表达式来描述正则语言。
正则表达式 是一种用于表示匹配简单文本模式的字符串的便捷记法。表达式 展示了四种正则表达式操作中的两种:连接(通过并置表示)和克林闭包(Kleene star)。其余两种操作出现在以下递归定义中。
形式化定义
-
以下都是正则表达式:
a) ,表示空语言/集合
b) ,表示仅含一个字符串的语言/集合
c) 每个字母表 中的字符 ,表示语言/集合
-
若 是正则表达式,则下列也是正则表达式:
a) (并集)
b) (连接)
c) (克林闭包)
d) (分组)
注意:一些作者(以及大多数编程环境)使用符号 表示并集。
每个正则表达式都代表一个语言,即所有匹配其模式的字符串构成的集合。形式上,我们将与正则表达式 对应的语言记作 ,因此有 ,,对字母表中的每个符号 有 。此外还满足以下关系:
上述定义是一种构造性定义。例如,在 的情况下,我们可以构造正则表达式 如下:
- 根据规则1–c,、 和 都是正则表达式。
- 根据规则2–c,、 和 是正则表达式。
- 再根据规则2–b(应用三次), 是一个正则表达式。
现在设 ,我们构造一个表示包含子串 的所有由 和 组成的字符串的语言的正则表达式。我们不关心 前后是什么内容,因此该语言的一个正则表达式为 。
满足定义的形式化构造过程如下:
- 根据规则1–c, 和 是正则表达式。
- 根据规则2–b(应用两次), 是正则表达式。
- 根据规则2–a, 是正则表达式。
- 根据规则2–d, 是正则表达式。
- 根据规则2–c, 是正则表达式。
- 最后根据规则2–b(应用两次), 是正则表达式。
以下是字母表 上的一些其他正则表达式示例。
| 正则语言 | 正则表达式 |
|---|---|
| 以 结尾的字符串 | |
| 以不同字符开头和结尾的字符串 | |
| 长度为偶数的字符串 | |
| 包含偶数个 的字符串 |
正则表达式操作符的优先级与代数中的类似:
- 分组具有最高优先级。
- 其次是克林闭包(类似于幂运算)。
- 然后是连接(类似于乘法)。
- 最后是并集(类似于加法)。
注意上表最后一个例子中的子表达式 。我们知道为了保证 的数量为偶数,必须成对引入两个 ,但它们不必相邻,因此我们在两个 之间插入 。
记住:正则表达式是一种用于文本处理的模式语言。
虽然我们习惯于使用指数作为重复的简写形式,但在正则表达式中不允许使用变量作为指数。例如, 作为 的简写是合法的正则表达式,因为 本身就是一个正则表达式;但 不是正则表达式。
记住:当 为常量时,表达式 是正则表达式;但当 为变量时, 不是正则表达式!
正则表达式也遵循某些代数规则,例如分配律: 以及 。此处顺序很重要,因为看似乘法的操作实际上是字符串连接,因此 。下表总结了重写正则表达式的常见规则。
注意:正则表达式的“相等”用于表示对应语言的等价性。当我们写作 而非 时,其含义是 。
| 规则 | 说明 |
|---|---|
| 并集满足交换律 | |
| 并集满足结合律 | |
| 并集满足幂等律 | |
| 并集的单位元是 | |
| 连接满足结合律 | |
| 连接的单位元是 | |
| 连接的零元是 | |
| 连接对并集满足左分配律 | |
| 连接对并集满足右分配律 | |
| 克林闭包满足幂等律 |
除了上述规则外,还有一些关于正则表达式的附加规则:
例如,我们可以得出 ,因为 。同理,,所以 。
再考虑表达式 。由于空集对第一项无影响,有 ,因此原表达式可简化为 。然而 ,故 是冗余的,使得原表达式等价于 。
正则表达式在定义语言记号的模式方面非常有用。例如,一个字母标识符符合模式 ,其中 表示字母表中的任意单个字母。由多个符号组成的变量名用尖括号括起以便清晰区分。编辑器和类UNIX文本工具常用一种简写记法,使用方括号界定字符范围,如 。
这种用方括号界定的组称为字符类,表示一组可接受字符中的任意一个。例如,[aeiou] 表示任意单个元音字符。使用连字符可以指定字符范围,因此 表示任意字母。加号()作为上标时意为“一个或多个”,因此我们可以直接写成 而非 。C语言中的十进制整数不能以0开头,其模式为 。这些特殊缩写并不属于我们所介绍的正则表达式的正式定义范畴,而是语言设计者和文本编辑程序为方便起见而采用的扩展功能。
Quiz
设 。
下列正则表达式中,哪一个所表示的语言与其他不同?