正则常规语法

当前位置:首页>正则>正则常规语法

正则常规语法

# PCRE2常规语法参考手册


## 1. 基本字符匹配


### 1.1 普通字符

- `a`, `b`, `c` - 匹配对应的字符


**示例:**

- 文本: "hello"

- 表达式: `h`

- 预期结果: 匹配"h"


### 1.2 转义字符

- `\.` - 匹配句号字符

- `\$` - 匹配美元符号

- `\\` - 匹配反斜杠


**示例:**

- 文本: "price is $10.50"

- 表达式: `\$`

- 预期结果: 匹配"$"


## 2. 字符类(Character Classes)


### 2.1 预定义字符类

- `\d` - 匹配数字字符(0-9)

- `\D` - 匹配非数字字符

- `\w` - 匹配单词字符(字母、数字、下划线)

- `\W` - 匹配非单词字符

- `\s` - 匹配空白字符(空格、制表符、换行符等)

- `\S` - 匹配非空白字符


**示例:**

- 文本: "Hello World 123!"

- 表达式: `\d+`

- 预期结果: 匹配"123"


- 文本: "Hello World 123!"

- 表达式: `\w+`

- 预期结果: 匹配"Hello"


- 文本: "Hello World 123!"

- 表达式: `\s+`

- 预期结果: 匹配空格


### 2.2 自定义字符类

- `[abc]` - 匹配方括号中的任一字符

- `[^abc]` - 匹配不在方括号中的任一字符

- `[a-z]` - 匹配a到z之间的任一字符

- `[A-Z]` - 匹配A到Z之间的任一字符

- `[0-9]` - 匹配0到9之间的任一数字


**示例:**

- 文本: "hello"

- 表达式: `[aeiou]`

- 预期结果: 匹配"e"和"o"


- 文本: "hello"

- 表达式: `[^aeiou]`

- 预期结果: 匹配"h"、"l"、"l"


## 3. 量词(Quantifiers)


### 3.1 基本量词

- `*` - 匹配零次或多次

- `+` - 匹配一次或多次

- `?` - 匹配零次或一次

- `{n}` - 匹配恰好n次

- `{n,}` - 匹配至少n次

- `{n,m}` - 匹配n到m次


**示例:**

- 文本: "aaaa"

- 表达式: `a*`

- 预期结果: 匹配"aaaa"


- 文本: "aaaa"

- 表达式: `a+`

- 预期结果: 匹配"aaaa"


- 文本: "aa"

- 表达式: `a?`

- 预期结果: 匹配"a"(两次)


- 文本: "aaabbbccc"

- 表达式: `a{3}`

- 预期结果: 匹配"aaa"


- 文本: "aaabbbccc"

- 表达式: `b{2,4}`

- 预期结果: 匹配"bbb"


### 3.2 非贪婪量词

- `*?` - 非贪婪匹配零次或多次

- `+?` - 非贪婪匹配一次或多次

- `??` - 非贪婪匹配零次或一次

- `{n,m}?` - 非贪婪匹配n到m次


**示例:**

- 文本: "aaaa"

- 表达式: `a*?`

- 预期结果: 匹配空字符串(零次匹配)


- 文本: "aaaa"

- 表达式: `a+?`

- 预期结果: 匹配"a"(最小的一次匹配)


## 4. 占有量词(Possessive Quantifiers)


占有量词表示贪婪匹配且不允许回溯。与普通量词的主要区别在于:

- 普通量词(如`*`):如果后续模式匹配失败,会回溯并减少匹配的字符数

- 占有量词(如`*+`):一旦匹配成功,就不会回溯,即使后续模式匹配失败


### 4.1 语法

- `*+`, `++`, `?+`, `{n,m}+` - 在普通限定符后加`+`


### 4.2 区别详解

- `*` vs `*+`:

  - `.*c` 在文本"abc"中会匹配"abc"(`.`匹配所有字符直到末尾,然后回溯直到找到`c`)

  - `.*+c` 在文本"abc"中不会匹配任何内容(`.*+`匹配所有字符,不留下任何字符给`c`,且不会回溯)


**示例:**

- 文本: "abc"

- 表达式: `a.*c`

- 预期结果: 匹配"abc"(普通量词允许回溯)


- 文本: "abc"

- 表达式: `a.*+c`

- 预期结果: 不匹配(占有量词不回溯,`.*+`消耗了所有剩余字符)


- 文本: "aaaa"

- 表达式: `a++b`

- 预期结果: 不匹配(a++消耗所有a,没有剩余的给b)


- 文本: "aaaa"

- 表达式: `a+a`

- 预期结果: 不匹配(a+消耗所有a,没有剩余的给后面的a)


## 5. 锚点(Anchors)


### 5.1 位置锚点

- `^` - 匹配字符串开始

- `$` - 匹配字符串结束

- `\b` - 匹配单词边界

- `\B` - 匹配非单词边界

- `\A` - 匹配字符串开始(不受多行模式影响)

- `\Z` - 匹配字符串结束或行尾的换行符前

- `\z` - 匹配字符串绝对结束

- `\G` - 匹配第一次匹配的位置


**示例:**

- 文本: "hello world"

- 表达式: `^hello`

- 预期结果: 匹配"hello"


- 文本: "hello world"

- 表达式: `world$`

- 预期结果: 匹配"world"


- 文本: "hello world"

- 表达式: `\bwo\w+`

- 预期结果: 匹配"world"


## 6. 分组和捕获(Groups and Captures)


### 6.1 捕获分组

- `(abc)` - 创建一个捕获组

- `(?:abc)` - 创建一个非捕获组


**示例:**

- 文本: "hello world"

- 表达式: `(hello)\s+(world)`

- 预期结果: 匹配"hello world",第一个捕获组"hello",第二个捕获组"world"


- 文本: "hello world"

- 表达式: `(?:hello)\s+(world)`

- 预期结果: 匹配"hello world",只有第二个捕获组"world"


### 6.2 命名捕获分组

- `(?<name>...)` - Perl/PCRE2命名捕获组

- `(?'name'...)` - .NET命名捕获组(在我们的COM组件中自动转换为PCRE2语法)

- `(?P<name>...)` - Python命名捕获组


**注意:**

- .NET风格的 `(?'name'...)` 语法在我们的COM组件中会被自动转换为PCRE2支持的 `(?<name>...)` 语法

- 如果在VB6/VBScript中遇到错误(如错误80004005),建议直接使用 `(?<name>...)` 语法


**示例:**

- 文本: "John Smith"

- 表达式: `(?<first>\w+)\s+(?<last>\w+)`

- 预期结果: 匹配"John Smith",命名捕获组first="John",last="Smith"


## 7. 选择操作符(Alternation)


### 7.1 基本选择

- `|` - 或操作符,匹配左边或右边的模式


**示例:**

- 文本: "apple"

- 表达式: `apple|banana`

- 预期结果: 匹配"apple"


- 文本: "banana"

- 表达式: `apple|banana`

- 预期结果: 匹配"banana"


## 8. 转义序列(Escape Sequences)


### 8.1 非打印字符

- `\t` - 制表符

- `\n` - 换行符

- `\r` - 回车符

- `\f` - 换页符

- `\a` - 响铃符

- `\e` - ESC字符


**示例:**

- 文本: "hello\tworld"

- 表达式: `\t`

- 预期结果: 匹配制表符


### 8.2 十六进制和八进制

- `\xFF` - 十六进制字符

- `\123` - 八进制字符


**示例:**

- 文本: "A"

- 表达式: `\x41`

- 预期结果: 匹配"A"(十六进制41是A的ASCII码)


## 9. Unicode属性(Unicode Properties)


### 9.1 Unicode通用类别

- `\p{L}` - 任何类型的字母

- `\p{Lu}` - 大写字母

- `\p{Ll}` - 小写字母

- `\p{Nd}` - 十进制数字

- `\p{P}` - 任何标点符号

- `\p{S}` - 任何符号

- `\p{Z}` - 任何分隔符


### 9.2 Unicode脚本

- `\p{Arabic}` - 阿拉伯语文字

- `\p{Han}` - 汉字

- `\p{Latin}` - 拉丁文字


**示例:**

- 文本: "Hello 世界"

- 表达式: `\p{L}+`

- 预期结果: 匹配"Hello"和"世界"


## 10. POSIX字符类


### 10.1 POSIX类

- `[:alnum:]` - 字母和数字

- `[:alpha:]` - 字母

- `[:ascii:]` - ASCII字符

- `[:blank:]` - 空格和制表符

- `[:cntrl:]` - 控制字符

- `[:digit:]` - 数字

- `[:graph:]` - 图形字符

- `[:lower:]` - 小写字母

- `[:print:]` - 可打印字符

- `[:punct:]` - 标点符号

- `[:space:]` - 空白字符

- `[:upper:]` - 大写字母

- `[:word:]` - 单词字符(字母、数字、下划线)

- `[:xdigit:]` - 十六进制数字


**示例:**

- 文本: "Hello123"

- 表达式: `[[:alpha:]]+`

- 预期结果: 匹配"Hello"


- 文本: "Hello123"

- 表达式: `[[:digit:]]+`

- 预期结果: 匹配"123"


## 11. 特殊构造


### 11.1 注释

- `(?#comment)` - 模式中的注释


**示例:**

- 文本: "hello"

- 表达式: `h(?#this is a comment)ello`

- 预期结果: 匹配"hello"


### 11.2 扩展模式

- `(?x)` - 启用扩展模式,忽略空格和注释


**示例:**

- 文本: "abc123"

- 表达式: `(?x)abc 123` (在扩展模式下)

- 预期结果: 匹配"abc123"


## 12. 实际应用示例


### 12.1 电子邮件验证

- 文本: "user@example.com"

- 表达式: `\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`

- 预期结果: 匹配"user@example.com"


### 12.2 IP地址验证

- 文本: "192.168.1.1"

- 表达式: `\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b`

- 预期结果: 匹配"192.168.1.1"


### 12.3 URL匹配

- 文本: "https://www.example.com"

- 表达式: `https?://[^\s/$.?#].[^\s]*`

- 预期结果: 匹配"https://www.example.com"


### 12.4 日期格式

- 文本: "2023-12-25"

- 表达式: `\d{4}-\d{2}-\d{2}`

- 预期结果: 匹配"2023-12-25"


## 13. 注意事项


1. 在字符类中,大部分元字符失去特殊意义,但仍需转义`]`和`^`

2. 转义字符在字符类中可能有不同的含义(如`\b`在字符类中表示退格符)

3. 量词作用于前面的原子元素,需要用括号分组以应用于多个字符

4. 某些字符类如`\d`、`\w`、`\s`在UTF模式下可能匹配更多字符

5. 不同语言的正则表达式实现可能存在细微差异

6. 在使用Unicode属性时,需要确保PCRE2编译时启用了Unicode支持

7. 关于命名捕获组语法,注意不同语言的差异:

   - .NET 使用 `(?'name'...)` 语法

   - Perl/PCRE2 使用 `(?<name>...)` 语法

   - 我们的COM组件支持这两种语法的转换



'\K 断点,表示之前的所有匹配都不作数,只匹配\K之后的内容

'(\w+ )\K(\d+)  "Hello 123"   只返回123


'(?<name>…)  命名捕获组Perl

'(?'name'…)  命名捕获组Perl & .NET

'(?P<name>…) 命名捕获组Python

'(?:…)       非捕获组,属于不返回捕获组

'(?|…)       重新编号捕获组,重新从1开始编号,属于不返回捕获组



Perl扩展字符类

'(?[...])  Perl扩展字符类基本语法

'(?[\p{Thai} & \p{Nd}])     Unicode 属性交集:匹配“泰国文字(Thai)且是十进制数字(Nd)”的字符

'(?[(x - y) & z])           分组与运算:使用小括号 ( ) 对集合运算进行分组

'   (?[(\d - [3]) & \p{Letter}])

'(?[ [^3] & \p{Nd} ])       匹配除 3 之外的十进制数字

'(?[ [:alpha:] - [z] ])     匹配除 z 之外的所有字母

'(?[ \d - [3] ])            \d 表示所有数字,减去 [3] 表示排除 3

'(?[ !\n & [:ascii:] ])      转义字符:\n 表示换行符,! 表示补集;匹配所有 ASCII 字符,排除换行符

'集合运算符

'  x|y, x+y  取并集(OR)         [\p{L} + \d],匹配字母或数字

'  x&y       取交集(AND)        [\p{L} & \p{M}] 匹配既是字母又是组合标记的字符

'  x-y       取差集(AND NOT)    [\d - [3]]  匹配数字但不包括 3

'  x^y       对称差集(XOR)      [\p{L} ^ [a-z]] 匹配字母集合中除 a-z 之外的字符

'  !x        取补集(NOT)        匹配非数字字符



捕获组引用

'(?R)            递归整个表达式

'(?n)            通过绝对编号引用捕获组

'(?+n)           通过相对编号引用捕获组

'(?-n)           通过相对编号引用捕获组

'(?&name)        通过名称引用捕获组 (Perl)

'(?P>name)       通过名称引用捕获组 (Python)

'\g<name>        通过名称引用捕获组 (Oniguruma)

'\g'name'        通过名称引用捕获组 (Oniguruma)

'\g<n>           通过绝对编号引用捕获组 (Oniguruma)

'\g'n'           通过绝对编号引用捕获组 (Oniguruma)

'\g<+n>          通过相对编号引用捕获组 (PCRE2扩展)

'\g'+n'          通过相对编号引用捕获组 (PCRE2扩展)

'\g<-n>          通过相对编号引用捕获组 (PCRE2扩展)

'\g'-n'          通过相对编号引用捕获组 (PCRE2扩展)