regex_package_overview.md•12.3 kB
# std.regex
## 功能介绍
regex 包使用正则表达式分析处理文本的能力,支持查找、分割、替换、验证等功能。
### regex 规则集
当前仓颉的正则表达式仅支持以下规则,使用不支持的规则会导致输出结果与预期不符。
| 字符 | 描述 |
| :----------: | ------------------------------------------------------------ |
| `\` | 将下一个字符标记为一个特殊字符(File Format Escape,清单见本表)、或一个原义字符(Identity Escape,有`^$()*+?.[{\|`共计 12 个)、或一个向后引用(backreferences)。例如,“n”匹配字符“n”。`\n`匹配一个换行符。序列`\`匹配`\`,而`(`则匹配`(`。 |
| `^` | 匹配输入字符串的开始位置。如果设置了 RegexOption 中的多行模式 multiLine(),^也匹配`\n`或`\r`之后的位置。 |
| `$` | 匹配输入字符串的结束位置。 |
| `*` | 匹配前面的子表达式零次或多次。例如,`zo*`能匹配`z`、`zo`以及`zoo`。`*`等价于`{0,}`。 |
| `+` | 匹配前面的子表达式一次或多次。例如,`zo+`能匹配`zo`以及`zoo`,但不能匹配`z`。`+`等价于`{1,}`。 |
| `?` | 匹配前面的子表达式零次或一次。例如,`do(es)?`可以匹配`does`中的`do`和`does`。`?`等价于`{0,1}`。 |
| `{n}` | n 是一个非负整数。匹配确定的 n 次。例如,`o{2}`不能匹配`Bob`中的`o`,但是能匹配`food`中的两个`o`。 |
| `{n,}` | n 是一个非负整数。至少匹配 n 次。例如,`o{2,}`不能匹配`Bob`中的`o`,但能匹配`foooood`中的所有`o`。`o{1,}`等价于`o+`。`o{0,}`则等价于`o*`。 |
| `{n,m}` | m 和 n 均为非负整数,其中 n<=m。最少匹配 n 次且最多匹配 m 次。例如,`o{1,3}`将匹配`fooooood`中的前三个`o`。`o{0,1}`等价于`o?`。请注意在逗号和两个数之间不能有空格。 |
| `?` | 非贪心量化(Non-greedy quantifiers):当该字符紧跟在任何一个其他重复修饰符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串`oooo`,`o+?`将匹配单个`o`,而`o+`将匹配所有`o`。 |
| `.` | 匹配除`\n`之外的任何单个字符。要匹配包括`\n`在内的任何字符,请使用像`(.\|\n)`的模式。 |
| `(pattern)` | 匹配 pattern 并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的 Matches 集合中得到。要匹配圆括号字符,请使用`\(`或`\)`。可带数量后缀。|
| `x\|y` | 没有包围在()里,其范围是整个正则表达式。例如,z\|food 能匹配`z`或`food`。(\?\:z\|f)ood 则匹配`zood`或`food`。 |
| `[xyz]` | 字符集合(character class)。匹配所包含的任意一个字符。例如,`[abc]`可以匹配`plain`中的`a`。特殊字符仅有反斜线\保持特殊含义,用于转义字符。其他特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位(或末尾)则仅作为普通字符。右方括号应转义出现,也可以作为首位字符出现。 |
| `[^xyz]` | 排除型字符集合(negated character classes)。匹配未列出的任意字符。例如,`[^abc]`可以匹配`plain`中的`plin`。 |
| `[a-z]` | 字符范围。匹配指定范围内的任意字符。例如,`[a-z]`可以匹配`a`到`z`范围内的任意小写字母字符。 |
| `[^a-z]` | 排除型的字符范围。匹配任何不在指定范围内的任意字符。例如,`[^a-z]`可以匹配任何不在`a`到`z`范围内的任意字符。 |
| `\b` | 匹配一个单词边界,也就是指单词和空格间的位置。例如,`er\b`可以匹配`never`中的`er`,但不能匹配`verb`中的`er`。 |
| `\B` | 匹配非单词边界。`er\B`能匹配`verb`中的`er`,但不能匹配`never`中的`er`。 |
| `\d` | 匹配一个数字字符。等价于`[0-9]`。 |
| `\D` | 匹配一个非数字字符。等价于`[^0-9]`。 |
| `\f` | 匹配一个换页符。等价于`\x0c`。 |
| `\n` | 匹配一个换行符。等价于`\x0a`。 |
| `\r` | 匹配一个回车符。等价于`\x0d`。 |
| `\s` | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于`[\f\n\r\t\v]`。 |
| `\S` | 匹配任何非空白字符。等价于`[^\f\n\r\t\v]`。 |
| `\t` | 匹配一个制表符。等价于`\x09`。 |
| `\v` | 匹配`\n\v\f\r\x85`。 |
| `\w` | 匹配包括下划线的任何单词字符。等价于`[A-Za-z0-9_]`。 |
| `\W` | 匹配任何非单词字符。等价于`[^A-Za-z0-9_]`。 |
| `\xnm` | 十六进制转义字符序列。匹配两个十六进制数字 nm 表示的字符。例如,`\x41`匹配`A`。正则表达式中可以使用 ASCII 码。 |
| `\num` | 向后引用(back-reference)一个子字符串(substring),该子字符串与正则表达式的第 num 个用括号围起来的捕捉群(capture group)子表达式(subexpression)匹配。其中 num 是从 1 开始的十进制正整数,Regex 捕获组上限为 63。例如:`(.)\1`匹配两个连续的相同字符。 |
| `(?:pattern)` | 匹配 pattern 但不获取匹配的子字符串(shy groups),也就是说这是一个非获取匹配,不存储匹配的子字符串用于向后引用。这在使用或字符`(\|)`来组合一个模式的各个部分是很有用。 |
| `(?=pattern)` | 正向肯定预查(look ahead positive assert),在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,`Windows(?=95\|98\|NT\|2000)`能匹配`Windows2000`中的`Windows`,但不能匹配`Windows3.1`中的`Windows`。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
| `(?!pattern)` | 正向否定预查(negative assert),在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如`Windows(?!95\|98\|NT\|2000)`能匹配`Windows3.1`中的`Windows`,但不能匹配`Windows2000`中的`Windows`。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
| `(?<=pattern)` | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,`(?<=95\|98\|NT\|2000)Windows`能匹配`2000Windows`中的`Windows`,但不能匹配`3.1Windows`中的`Windows`。 |
| `(?<!pattern)` | 反向否定预查,与正向否定预查类似,只是方向相反。例如`(?<!95\|98\|NT\|2000)Windows`能匹配`3.1Windows`中的`Windows`,但不能匹配`2000Windows`中的`Windows`。 |
| `(?i)` | 通过规则指定部分规则忽略大小写。当前 Regex 仅支持全局忽略大小写,当该选项被指定时,会被当做全局忽略大小写对待。 |
| `(?-i)` | 通过规则指定部分规则大小写敏感。 当前 Regex 默认大小写敏感,该选项仅做编译兼容处理,不做敏感处理。 |
| `+` | 单独一个加号,不是转义的`\+`。 |
| `*` | 单独一个星号,不是转义的`\*`。 |
| `-` | 单独一个减号,不是转义的`\-`。 |
| `]` | 单独一个右中括号,不是转义的`\]`。 |
| `}` | 单独一个右大括号,不是转义的`\}`。 |
| `[[:alpha:]]` | 表示任意大小写字母。 |
| `[[:^alpha:]]` | 表示除大小写字母以外的任意字符。|
| `[[:lower:]]` | 表示任意小写字母。 |
| `[[:^lower:]]` | 表示除小写字母以外的任意字符。 |
| `[[:upper:]]` | 表示任意大写字母。 |
| `[[:^upper:]]` | 表示除大写字母以外的任意字符。 |
| `[[:digit:]]` | 表示0到9之间的任意单个数字。 |
| `[[:^digit:]]` | 表示除0到9之间的单个数字以外的任意字符。 |
| `[[:xdigit:]]` | 表示十六进制的字母和数字。 |
| `[[:^xdigit:]]` | 表示除十六进制的字母和数字以外的任意字符。 |
| `[[:alnum:]]` | 表示任意数字或字母。 |
| `[[:^alnum:]]` | 表示除数字或字母以外的任意字符。 |
| `[[:space:]]` | 表示任意空白字符,包括"空格"、"tab键"等。 |
| `[[:^space:]]` | 表示除空白字符以外的任意字符。 |
| `[[:punct:]]` | 表示任意标点符号。 |
| `[[:^punct:]]` | 表示除任意标点符号以外的任意字符。|
在仓颉中,还存在一些特殊的规则:
1. `?`、`+`、`*` 前面的字符不可量化时,会被忽略;特例:`(*`、`|*`、`*` 开头时 `*` 会被视为普通字符。
2. `*?` 在匹配全部 `*?` 之前的字符组成的字符串时,会匹配不到该字符。
3. 正则表达式的捕获组的最大个数为 63,编译后的最大规则长度为 65535。
4. 暂不支持的场景:((pattern1){m1,n1}pattern2){m2,n2},即:
- 组定义 1 被{m1,n1}修饰;
- 组定义 1 被组定义 2 包裹;
- 组定义 2 被{m2,n2}修饰。
5. 待匹配字符串需要用户自行保障不包含 `\0`,否则会得到预期以外的结果,甚至会陷入死循环无法退出。
> **警告:**
>
> 当前实现中未对规则为`{n}`、`{n,}`、`{n,m}`创建的最小或者最大重复次数进行限制,重复次数过大会造成创建正则匹配器时占用大量的CPU和内存资源,甚至会触发栈溢出异常退出,从而导致执行时间过长或者 `ReDos`攻击。
## API 列表
### 类
| 类名 | 功能 |
| --------------------------- | ------------------------ |
| [Matcher <sup>(deprecated)</sup>](./regex_package_api/regex_package_classes.md#class-matcher-deprecated) | 正则匹配器,用于扫描输入序列并进行匹配。 |
| [Regex](./regex_package_api/regex_package_classes.md#class-regex) | 用来指定编译类型和输入序列。 |
| [RegexOption <sup>(deprecated)</sup>](./regex_package_api/regex_package_classes.md#class-regexoption-deprecated) | 用于指定正则匹配的模式。 |
### 枚举
| 枚举名 | 功能 |
| --------------------------- | ------------------------ |
| [RegexFlag](./regex_package_api/regex_package_enums.md#enum-regexflag) | 用于指定正则匹配的模式。 |
### 结构体
| 结构体名 | 功能 |
| --------------------------- | ------------------------ |
| [MatchData](./regex_package_api/regex_package_structs.md#struct-matchdata) | 存储正则表达式匹配结果,并提供对正则匹配结果进行查询的函数。 |
| [Position](./regex_package_api/regex_package_structs.md#struct-position) | 用来存储位置信息,表示的是一个前闭后开区间。 |
### 异常类
| 异常类名 | 功能 |
| --------------------------- | ------------------------ |
| [RegexException](./regex_package_api/regex_package_exceptions.md#class-regexexception) | 提供 regex 相关的异常处理。 |