正则常规语法

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

正则常规语法

# 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扩展)