正则表达式引擎

DEELX 正则表达式引擎（v1.2）

RegExLab 的研究开发项目。 [更新日期：2006年9月29日]

DEELX 是一个在 C++ 环境下的与 Perl 兼容的正则表达式引擎。是 RegExLab 开展的一个研究开发项目。

基本特点：
  • 支持与 Perl 兼容的正则表达式语法。
  • 支持 IGNORECASE, SINGLELINE, MULTILINE 等常见匹配模式。
  • 兼容性强，能在 vc6, vc7, vc8, gcc, Turbo C++ 等大多数 C++ 环境编译。
  • 支持命名分组，条件表达式，递归表达式等多种高级特性。（1.2版本新特点）

与 GRETA、boost 相比，DEELX 独到之处：
  • 完全使用模版库编写，支持 char, wchar_t, int 等以及其他基类型版本。
  • 全部代码位于一个头文件（.h）中， 比任何引擎都使用简单和方便。
  • 支持从右向左匹配模式，可从文本结束位置向前搜索匹配。
  • 可防止零长度子匹配循环无限次而产生的死循环。（1.2版本新特点）

DEELX 不足之处：
  • DEELX 是完全免费的实验室产品。
  • 为弥补实验室产品的不足，本站同步推出了与本引擎完全兼容的调试工具：Match Tracer。

源代码下载：

[ [image] 下载：DEELX]

DEELX 可免费用于个人用途及商业用途。

更多参考：

[ [image] 正则表达式语法] - 详细介绍 DEELX 支持的正则表达式语法。

[ [image] 编程帮助] - 编程指南，详细介绍如何将 DEELX 用于你的 C++ 项目。

[ [image] 表达式工具 Match Tracer] - 推荐使用正则表达式可视化编写及调试工具。

简介

正则语法

编程帮助

示例

下载

表达式工具

RegExLab.com © 2005 - All Rights Reserved.


性能与特点

DEELX 正则引擎性能与特点

C++ 环境下的正则表达式引擎，RegExLab 的研究开发项目。

本页内容：
  • 使用模版库编写
  • 从右向左匹配模式
  • 反向预搜索
  • 移植简单
  • 兼容性
  • 支持命名分组
  • 条件表达式
  • 递归表达式
  • 防止死循环
使用模板库编写

DEELX 正则引擎全部采用模板 template 编写，可将 DEELX 用于 char, wchar_t 以及其他基类型，比如 unsigned char, int 等。但只能是简单数据类型，不可以是 struct 或者 union 等复合类型。

比如：

#include "deelx.h"

int pattern[] = {65, '+', 66, 0}; // 0 to indicate end
int text[] = {180000, 65, 65, 66, 0};

CRegexpT <int> regexp(pattern);
MatchResult result = regexp.Match(text);

if(result.IsMatched())
{
printf("start at: %d\nlength: %d\n", result.GetStart(),
result.GetEnd() - result.GetStart());
}

更多详情可参考：

[ [image] 编程帮助]

从右向左（RIGHTTOLEFT）匹配模式

DEELX 支持从右向左匹配模式，可使表达式从文本结束位置向前查找匹配。在表达式中，右侧的表达式比左侧的表达式先匹配。编写用来在“从右向左”模式下使用表达式与普通情况下使用的表达式并没有什么不同。匹配次数修饰符（*, +, {n}, ……）仍然位于被修饰部分的右侧；^ 仍然匹配文本开始；正向预搜索 (?=xxx) 仍然是向右搜索，而不是向左；分组（group）编号仍然是从左向右进行编号；等等。

需要注意的是，当使用了“从右向左”模式后，右侧的表达式会先进行匹配。这时如果使用了反向引用，那么被引用的分组（group）应该是在右侧。

比如：

“从右向左”模式下

正常模式下

\2(.*?)('|")

('|")(.*?)\1

递归匹配没有这个限制，不管是否是“从右向左”模式，下边的两种写法都是可以的：

(?2)(.*?)(")

(")(.*?)(?1)
反向预搜索（反向零宽度断言）

“反向预搜索”就是在匹配过程中，要求当前位置左侧的文本必须符合某个条件，格式为 (?<=xxx) 或者 (?<!xxx)。与 \b 类似，本身不匹配任何文本，只是对该当前位置设置一个条件。比如：

表达式

说明

\b

要求当前位置为单词的边界，也就是说，左右两侧只能有一侧是字母或数字。

(?<!\w)(?=\w)

要求当前位置为单词开头，只能是右侧是字母或数字。

(?<=\w)(?!\w)

要求当前位置为单词结尾，只能是左侧是字母或数字。

关于反向预搜索中包含的表达式，Perl, Java, GRETA 以及 DEELX 的细节都不相同：

引擎

说明

举例

Perl

只能使用固定长度的反向预搜索。

(?<=\t)print

Java

允许使用不定长度的反向预搜索，但必须要有最大长度。

(?<=\{\s{0,100})print

GRETA

允许使用没有长度限制，但否定格式存在一些问题。

(?<=\{\s*)print

DEELX 中的反向预搜索：

DEELX 采用 RIGHTTOLEFT 模式来匹配“反向预搜索”中的表达式。使反向预搜索与正向预搜索在逻辑上完全相同，而方向相反。因此，在 DEELX 中，反向预搜索与正向预搜索一样，没有长度限制。

比如，在 DEELX 引擎中：

文本

表达式

匹配结果

{print}

(?<!\{\s*)print

匹配失败

(?<=\{\s*)print

匹配成功

移植简单

DEELX 全部使用模板库编写，因此没有任何 cpp 或者 lib 文件。全部代码位于一个头文件（deelx.h）中。使用时，不需要为 DEELX 创建 project，也不需要添加任何 cpp 或者静态库 lib 文件。运行时，也不依赖专门的动态库。

使用 DEELX 正则引擎时，只需要简单地添加一个 include 就可以了：

#include "deelx.h"

由于 deelx.h 已经直接包含到你的项目中，因此不会存在 Runtime Library 与主项目不同的问题，也不用担心会产生连接错误的问题。

兼容性

DEELX 采用纯 C++ 代码编写，没有使用任何 STL 类或者 MFC 类。DEELX 已测试能够在以下编译器及操作系统中编译：

编译器

版本

操作系统

备注

VC++

6.0, 7.1, 8.0

Windows

GCC

3.4

Cygwin

GCC

3.4

Linux

Turbo C++

3.0

DOS

C++ Builder

6.0

Windows

Borland C++

5.5

Windows

GCC

2.7

FreeBSD 2.2

GCC

3.4

Solaris 10 Unix

http://www.unix-center.net/

在其他平台以及其他编译器下，我们还未进行测试。

如果您在其他的编译器或者其他系统下编译成功或者编译失败了，可以通过 regexlab@gmail.com 告诉我们，我们将非常感谢。

命名分组

DEELX 支持 Python 及 .NET 风格的命名分组。命名分组的编号顺序按照 .NET 风格。DEELX 支持以下格式的命名分组：

表达式

风格

说明

(?P<the_name>xxxx)

Python

定义一个命名 'the_name' 的命名分组

(?<the_name>xxxx)

.NET

(?'the_name'xxxx)

匹配成功后，可通过分组的命名来获取分组捕获到的内容。

DEELX 允许多个命名分组的名字相同，这时它们捕获到的内容会放在同一个分组编号下。在逻辑上，它们是同一个分组，比如： (?<string>".*?")|(?<string>'.*?') 。如果两个命名相同分组之间有包含关系，那么被包含的那个分组将不进行捕获，比如： (?<number>(?<number>\d+)\.?) 。

此外，与命名分组相关的功能有：反向引用，递归表达式，条件表达式，以及替换操作。

功能

表达式

风格

说明

反向引用

\g<the_name>

Python

反向引用命名分组 'the_name'

\k<the_name>

.NET

\k'the_name'

递归表达式

(?R<the_name>)

递归表达式引用命名分组 'the_name'

(?R'the_name')

条件表达式

(?(the_name)yes|no)

.NET

根据分组 'the_name' 是否有捕获

替换操作

${the_name}

替换时，表示分组 'the_name' 的内容

条件表达式

条件表达式就是根据某个条件是否成立，来选择匹配 2 个可选表达式中的其中一个。可以用于条件表达式的条件有两种类型：

  1. 指定分组（group）是否进行了捕获。
  2. 文本中当前位置是否可以与指定表达式匹配。

条件表达式的举例及说明：

表达式

条件特点

条件说明

(?(1)yes|no)

条件为数字

分组1如果有捕获，则进行 yes 部分匹配，否则 no 部分

(?(?=a)aa|bbb)

条件为预搜索

如果当前位置右侧是 a，则进行匹配 aa，否则匹配 bbb

(?(xxx)aa|bbb)

不与分组命名吻合

如果不与任何分组命名吻合，则视为 (?=xxx) 相同

(?(name)yes|no)

与分组命名吻合

如果与某分组命名吻合，则视为判断该分组是否进行捕获

补充说明：

  1. 如果表达式为 RIGHTTOLEFT 模式，那么 (?(xxx)aa|bbb) 与 (?(?<=xxx)aa|bbb) 相同。
  2. 如果条件表达式只有一个选择项，那么这个选项是在条件成立时进行匹配。
  3. 如果条件表达式中，使用“|”进行分隔的选项多于2个，则只有第一个“|”被视为条件表达式选项分隔符。比如： (?(?=xxx)yes|no1|no2)，条件成立时，匹配 yes 部分，否则匹配 "no1|no2"。
递归表达式

“递归表达式”就是对另一部分子表达式本身的引用，而不是对其匹配结果的引用。举例说明：

表达式

等效的表达式1

等效的表达式2

可以匹配

(\w)(?1)

(\w)(\w)

ab

(?1)(\w(?2))(\d)

(?1)(\w(\d))(\d)

(\w(\d))(\w(\d))(\d)

a1b23

如果被引用的表达式又包含自身，则形成了递归引用。举例说明：

表达式

等效1

等效2

可以匹配

(\w(?1)?)

(\w(\w(?1)?)?)

(\w+)

ghjk5……

\(([^()]|(?R))*\)

\(([^()]|\(([^()]|(?R))*\))*\)

(a * (c + 2))

递归表达式的格式有：

格式

说明

(?R)

对整个表达式的递归引用。

(?R1)，(?R2)

对指定分组的递归引用。

(?1)，(?2)

(?R<named>)

对指定命名分组的递归引用。

(?R'named')

防止死循环

能匹配零长度的子表达式，如果在被修饰匹配次数时被修饰为可以匹配任意次，则在很多正则引擎中，容易出现死循环。为此，DEELX 已通过技术手段，防止死循环的出现。

比如，容易出现死循环的表达式：

表达式

说明

(a*)*

因 a* 可以匹配零长度，整个表达式可能死循环。但在 DEELX 中不会出现死循环。

(a|b|c?)*

其中一个选项可以匹配零长度，也容易出现死循环。但在 DEELX 中不会出现死循环。

简介

正则语法


表达式语法

DEELX 正则表达式语法

C++ 环境下的正则表达式引擎，RegExLab 的研究开发项目。

概述

DEELX 支持 Perl 兼容的正则表达式语法。DEELX 支持的正则表达式语法与大多数正则引擎基本相同。在扩展语法部分，DEELX 实现了一些独到的功能。

有经验的用户，可参见 DEELX 性能与特点。

目录
  1. 基本语法
    1. 普通字符
    2. 简单的转义字符
    3. 转义字符（\Q...\E）
    4. 字符集合
    5. 自定义字符集合
    6. 匹配次数限定符
    7. 字符边界
    8. 选择表达式
    9. 分组
    10. 命名分组
    11. 反向引用

  2. 扩展语法
    1. 注释
    2. 模式修改符
    3. 非捕获分组
    4. 预搜索（零宽度断言）
    5. 独立表达式
    6. 条件表达式
    7. 递归表达式

  3. 匹配模式
    1. 忽略大小写（IGNORECASE）
    2. 单行模式（SINGLELINE）
    3. 多行模式（MULTILINE）
    4. 全局模式（GLOBAL）
    5. 从右向左模式（RIGHTTOLEFT）
    6. 扩展模式（EXTENDED）

  4. 替换
    1. $number
    2. ${name}
    3. $$
    4. $&
    5. $`
    6. $'
    7. $+
    8. $_

参见

[ [image] 编程帮助] - 编程指南，详细介绍如何将 DEELX 用于你的 C++ 项目。

[ [image] 表达式工具 Match Tracer] - 推荐使用正则表达式可视化编写及调试工具。


基本语法

DEELX 正则表达式基本语法

回到：目录 | 下一页：普通字符

概述

DEELX 支持 Perl 兼容的正则表达式基本语法。基本语法规则在各个不同的正则引擎中表现基本一致。

本节内容

普通字符
    字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号，都是"普通字符"。

简单的转义字符
    一些不便书写的字符，以及后边章节中特殊定义的符号，采用在前面加 "\" 的方法来书写。

转义字符（\Q...\E）
    使用 \Q 开始，\E 结束，可使中间的标点符号失去正则语法所定义的特殊意义。

字符集合
    可以与 '多个字符' 中的任意一个字符匹配的表示方法。

自定义字符集合
    使用方括号 [ ] 自定义与 '多个字符' 中的任意一个字符匹配的表示方法。

匹配次数限定符
    使另外一个子表达式可以重复进行匹配。

字符边界
    本身不匹配任何字符，但对字符边界设置了条件。

选择表达式
    使用“|”将多段表达式分隔，可匹配其中任意一段。

分组
    使用括号 ( ) 包含的表达式，匹配到的文本可以单独获取。

命名分组
    给分组命名，该分组的匹配结果可通过名字来单独获取。

反向引用
    匹配过程中，对分组的匹配结果进行引用。


DEELX 正则表达式基本语法：普通字符

回到：目录 | 上一页：基本语法概述 | 下一页：简单转义字符

普通字符

字母、数字、汉字、下划线，以及没有被定义特殊意义的标点符号，都是 "普通字符"。

说明

"普通字符" 在匹配时，匹配与之相同的一个字符。

如果一个表达式中，所有的字符都是 "普通字符"，那么这个表达式的匹配操作，实际上就是一个普通的 "字符串查找" 操作。


DEELX 正则表达式基本语法：简单的转义字符

回到：目录 | 上一页：普通字符 | 下一页：转义字符（\Q...\E）

简单的转义字符

一些不便书写的字符，比如换行符，制表符等，使用 \n，\t 来表示。另外有一些标点符号在正则表达式中，被定义了特殊的意义，因此需要在前面加 "\" 进行转义后，匹配该字符本身。

说明

DEELX 中的转义字符：

转义符

说明

\a

响铃符 = \x07

\f

换页符 = \x0C

\n

换行符 = \x0A

\r

回车符 = \x0D

\t

制表符 = \x09

\v

垂直制表符 = \x0B

\e

ESC 符 = \x1B

\x20

使用两位十六进制表示形式，可与该编号的字符匹配

\u002B

使用四位十六进制表示形式，可与该编号的字符匹配

\x{20A060}

使用任意位十六进制表示形式，可与该编号的字符匹配

在 DEELX 中被定义了特殊的意义，因而需要在前面添加 "\" 来匹配该字符本身的标点符号：

字符

说明

^

匹配输入字符串的开始位置。要匹配 "^" 字符本身，请使用 "\^"

$

匹配输入字符串的结尾位置。要匹配 "$" 字符本身，请使用 "\$"

( )

标记一个子表达式的开始和结束位置。要匹配小括号，请使用 "\(" 和 "\)"

[ ]

用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号，请使用 "\[" 和 "\]"

{ }

修饰匹配次数的符号。要匹配大括号，请使用 "\{" 和 "\}"

.

匹配除了换行符（\n）以外的任意一个字符。要匹配小数点本身，请使用 "\."

?

修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身，请使用 "\?"

+

修饰匹配次数为至少 1 次。要匹配 "+" 字符本身，请使用 "\+"

*

修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身，请使用 "\*"

|

左右两边表达式之间 "或" 关系。匹配 "|" 本身，请使用 "\|"


转义字符

DEELX 正则表达式基本语法：转义字符（\Q...\E）

回到：目录 | 上一页：简单的转义字符 | 下一页：字符集合

转义字符 \Q...\E

使用 \Q 开始，\E 结束，可使中间的标点符号失去特殊意义，将中间的字符作为普通字符。

使用 \U 开始，\E 结束，除了具有 \Q...\E 相同的功能外，还将中间的小写字母转换成大写。在大小写敏感模式下，只能与大写文本匹配。

使用 \L 开始，\E 结束，除了具有 \Q...\E 相同的功能外，还将中间的大写字母转换成小写。在大小写敏感模式下，只能与小写文本匹配。

说明

\Q...\E 适合用于：表达式中需要比较长的普通文本，而其中包含了特殊符号。

举例

表达式

说明

\Q(a+b)*3\E

可匹配文本 "(a+b)*3"。

\(a\+b\)\*3

如果不使用 \Q...\E 进行转义，则对每个特殊符号进行转义。


DEELX 正则表达式基本语法：字符集合

回到：目录 | 上一页：转义字符（\Q...\E） | 下一页：自定义字符集合

字符集合

可以匹配 "多个字符" 其中任意一个字符的正则表达式。虽然是 "多个字符"，但每次只能匹配其中一个。

说明

DEELX 正则表达式中标准的字符集合有：

字符集合

说明

.

小数点可以匹配除了换行符（\n）以外的任意一个字符

\w

可以匹配任何一个字母或者数字或者下划线

\W

W大写，可以匹配任何一个字母或者数字或者下划线以外的字符

\s

可以匹配空格、制表符、换页符等空白字符的其中任意一个

\S

S大写，可以匹配任何一个空白字符以外的字符

\d

可以匹配任何一个 0~9 数字字符

\D

D大写，可以匹配任何一个非数字字符

[:alpha:]

POSIX 格式，可以匹配任何一个字母

[:^alpha:]

POSIX 否定格式，可以匹配任何一个字母以外的字符

如果正则表达式匹配模式为 SINGLELINE，小数点可以匹配包含换行符在内的任一字符。更多详情，参见正则表达式匹配模式。

DEELX 支持的 POSIX 字符集合定义有：

POSIX 字符集合

说明

[:alnum:]

任何一个字母或数字（A - Z, a - z, 0 - 9）

[:alpha:]

任何一个字母（A - Z, a - z）

[:ascii:]

任何一个 ASCII 范围内字符（\x00 – \x7F）

[:cntrl:]

任何一个控制字符（\x00 – \x1F, \x7F）

[:digit:]

任何一个数字（0 – 9）

[:print:]

任何一个可显示的 ASCII 字符（\x20 – \x7E）

[:space:]

任何一个空白字符（\x09 – \x0D, \x20）

[:graph:]

任何一个可显示的 ASCII 字符，不包含空格（\x21 – \x7E）

[:lower:]

任何一个小写字母（a – z）

[:punct:]

可显示字符 [:print:] 中除去字母数字 [:alnum:]

[:upper:]

任何一个大写字母（A – Z）

[:xdigit:]

任何一个十六进制数字（0 - 9, A - F, a - f）

[:blank:]

空格或者制表符（\x20, \x09）

所有的 POSIX 字符集合，与 [:^alpha:] 类似 ，当 [: 之后为 ^ 时，表示相应字符集合之外的字符。


自定义字符集合

DEELX 正则表达式基本语法：自定义字符集合

回到：目录 | 上一页：字符集合 | 下一页：匹配次数限定符

自定义字符集合 [ ]

用中括号 [ ] 包含多个字符，可以匹配所包含的字符中的任意一个。同样，每次只能匹配其中一个。

用中括号 [^ ] 包含多个字符，构成否定格式，可以匹配所包含的字符之外的任意一个字符。

说明

正则表达式中的特殊符号，如果被包含于中括号中，则失去特殊意义，但 \ [ ] : ^ - 除外。

标准字符集合，除小数点(.)外，如果被包含于中括号中，自定义字符集合将包含该集合。
比如：[\d.\-+]，将可以匹配数字，小数点和 + - 符号。（小数点和 + 号失去特殊意义）

用减号相连的 2 个普通字符，自定义字符集合将包含该范围。
比如：[\dA-Fa-f]，将可以匹配 0 - 9, A - F, a - f。

自定义字符集合可以包含 POSIX 字符集合。

不管正则表达式匹配模式是否是 IGNORECASE，字符集合在匹配时，都是要区分大小写的。更多详情，参见正则表达式匹配模式。


DEELX 正则表达式基本语法：匹配次数限定符

回到：目录 | 上一页：自定义字符集合 | 下一页：字符边界

匹配次数限定符

使被修饰的表达式可多次重复匹配的修饰符。

说明

可使被修饰的表达式重复固定次数，也可以限定一定的重复匹配的次数范围。

在限定符之后的表达式能够匹配成功的情况下，不定次数的限定符总是尽可能的多匹配。如果之后的表达式匹配失败，限定符可适当“让出”能够匹配的字符，以使整个表达式匹配成功。这种模式就叫“贪婪模式”。

限定符

说明

{n}

表达式固定重复n次，比如："\w{2}" 相当于 "\w\w"

{m, n}

表达式尽可能重复n次，至少重复m次："ba{1,3}"可以匹配 "ba"或"baa"或"baaa"

{m, }

表达式尽可能的多匹配，至少重复m次："\w\d{2,}"可以匹配 "a12","x456"...

?

表达式尽可能匹配1次，也可以不匹配，相当于 {0, 1}

+

表达式尽可能的多匹配，至少匹配1次，相当于 {1, }

*

表达式尽可能的多匹配，最少可以不匹配，相当于 {0, }

“勉强模式”限定符：

在限定符之后添加问号(?)，则使限定符成为“勉强模式”。勉强模式的限定符，总是尽可能少的匹配。如果之后的表达式匹配失败，勉强模式也可以尽可能少的再匹配一些，以使整个表达式匹配成功。

限定符

说明

{m, n}?

表达式尽量只匹配m次，最多重复n次。

{m, }?

表达式尽量只匹配m次，最多可以匹配任意次。

??

表达式尽量不匹配，最多匹配1次，相当于 {0, 1}?

+?

表达式尽量只匹配1次，最多可匹配任意次，相当于 {1, }?

*?

表达式尽量不匹配，最多可匹配任意次，相当于 {0, }?

“占有模式”限定符：

在限定符之后添加加号(+)，则使限定符成为“占有模式”。占有模式的限定符，总是尽可能多的匹配。与“贪婪模式”不同的是，即使之后的表达式匹配失败，“占有模式”也不会“让出”自己能够匹配的字符。

限定符

说明

{m, n}+

表达式尽可能重复n次，至少重复m次。

{m, }+

表达式尽可能的多匹配，至少重复m次。

?+

表达式尽可能匹配1次，也可以不匹配，相当于 {0, 1}+

++

表达式尽可能的多匹配，至少匹配1次，相当于 {1, }+

*+

表达式尽可能的多匹配，最少可以不匹配，相当于 {0, }+


DEELX 正则表达式基本语法：字符边界

回到：目录 | 上一页：匹配次数限定符 | 下一页：选择表达式

字符边界

本身不匹配任何字符，只对字符边界和字符间缝隙附加条件的表达式。

说明

有些正则表达式中的符号，可以对文本中当前所在位置作限制条件：

边界条件

说明

^

当前位置必须是文本开始位置

$

当前位置必须是文本结束位置

\b

当前位置的左右两侧，只能有一侧是字母数字或下划线

如果正则表达式的匹配模式为 MULTILINE 模式，^ 可匹配一行文本的行首，$ 可匹配一行文本的行末。更多详情，参见正则表达式匹配模式。

当 \b 被包含于字符集合中时，\b 代表退格符（ASCII码 = 8）。


选择表达式

DEELX 正则表达式基本语法：选择表达式

回到：目录 | 上一页：字符边界 | 下一页：分组

选择表达式 xxx | xxx

使用竖线 "|" 分隔多段表达式，整个表达式可匹配其中任意一段。

说明

正则引擎总是从左向右进行尝试匹配，如果每一段表达式都匹配失败，则整个表达式匹配失败。


分组

DEELX 正则表达式基本语法：分组

回到：目录 | 上一页：选择表达式 | 下一页：命名分组

分组 ( )

用括号 ( ) 将其他表达式包含，可以使被包含的表达式组成一个整体，在被修饰匹配次数时，可作为整体被修饰。

另外，用括号包含的表达式，所匹配到的内容将单独作记录，匹配过程中或结束后可以被获取。

说明

每一对括号会分配一个编号，使用 () 的捕获根据左括号的顺序从 1 开始自动编号。捕获元素编号为零的第一个捕获是由整个正则表达式模式匹配的文本。


命名分组

DEELX 正则表达式基本语法：命名分组

回到：目录 | 上一页：分组 | 下一页：反向引用

命名分组 (?<name>xxx)

与普通分组一样的功能，并且将匹配的子字符串捕获到一个组名称或编号名称中。

在获得匹配结果时，可通过分组名进行获取。

说明

命名捕获根据左括号的从左到右的顺序按顺序编号（与非命名捕获类似），但在对所有非命名捕获进行计数之后才开始对命名捕获进行编号。

DEELX 允许多个命名分组的名字相同，这时它们捕获到的内容会放在同一个分组编号下。在逻辑上，它们是同一个分组。

如果两个命名相同分组之间有包含关系，那么被包含的那个分组将不进行捕获。


反向引用

DEELX 正则表达式基本语法：反向引用

回到：目录 | 上一页：命名分组 | 下一页：扩展语法概述

反向引用 \nnn

对指定分组已捕获的字符串进行引用，要求文本中当前位置开始的字符串，必须和指定分组捕获到的字符串一致。

说明

DEELX 支持的反向引用格式：

反向引用

说明

\nnn

对指定编号的分组进行反向引用

\g<name>

对指定名字的命名分组进行反向引用

\k<name>

\k'name'

另外，如果被引用的捕获组（括号对）未进行捕获时，则该反向引用将匹配失败。

DEELX 最多将 3 位数字识别为反向引用，如果想在表达式中表示 \1 外加一个字符 2 ，那么应该写成 \0012。在 DEELX 中，不管是否有第 12 对括号，写成 \12 都表示对第 12 对括号的引用。

DEELX 不将 \nnn 格式识别为 8 进制数，参见简单的转义字符。


扩展语法

DEELX 正则表达式扩展语法

回到：目录 | 上一页：反向引用 | 下一页：注释

概述

DEELX 支持 Perl 兼容的多数正则表达式扩展语法。扩展语法规则在各个不同的正则引擎中的表现不完全相同，在一些细节上可能有些区别。使用扩展语法时，需要阅读文档后使用。

本节内容

注释
    为使表达式有更好的阅读性，可在表达式中添加注释。

模式修改符
    表达式中间，可对表达式的模式进行修改。

非捕获分组
    如果分组的目的仅是包装成一个整体，而并不是为了捕获，则可以使用非捕获组，节省内存资源。

预搜索（零宽度断言）
    更灵活，更强大的字符边界条件。

独立表达式
    后边的表达式即使匹配不成功，也不进行回朔的表达式。

条件表达式
    根据某个条件，选择性进行匹配的表达式。

递归表达式
    可递归匹配嵌套结构文本的表达式。


注释

DEELX 正则表达式扩展语法：注释

回到：目录 | 上一页：扩展语法概述 | 下一页：模式修改符

注释 (?#xxx)

格式 (?# xxx ) 可用来表示一段注释。

说明

注释可以位于表达式中任意地方，但不可以出现在转义字符（\）与被转移字符中间。比如：\(?# xxx )w 是不可以的，这样写的效果实际上是第一个括号被转义成普通字符了。

在 (?# 之后，遇到第一个反括号将表示注释结束。因此，想把注释写成 (?# x()xx ) 或者 (?# x\)xx ) 都是不可以的。注释中的反斜杠（\），不代表转义字符。


模式修改符

DEELX 正则表达式扩展语法：模式修改符

回到：目录 | 上一页：注释 | 下一页：非捕获分组

模式修改符 (?ismg-ismg)

在正则表达式中间，对匹配模式进行修改。

说明

关于匹配模式，请参见匹配模式。

DEELX 支持对 IGNORECASE, SINGLELINE, MULITLINE, GLOBAL 进行修改。

修改后的匹配模式，只对当前小括号内，修改符之后的部分起作用。比如：

表达式

说明

a(b(?i)c)d

增加 i - IGNORECASE 模式，只对 c 起作用。表达式可以匹配 "abcd" 和 "abCd"


非捕获分组

DEELX 正则表达式扩展语法：非捕获组

回到：目录 | 上一页：模式修改符 | 下一页：预搜索（零宽度断言）

非捕获组 (?:xxx)

使用 (?: ) 包含其他表达式，可使被包含的表达式组成一个整体，在被修饰匹配次数时，可作为整体被修饰。

说明

与普通分组不同的是，非捕获组不记录所匹配的内容，比普通分组更节约内存资源。

通过格式 (?ismg-ismg:xxx) 可对匹配模式进行修改，修改后的模式只对当前非捕获组内部起作用。


预搜索（零宽度断言）

DEELX 正则表达式扩展语法：预搜索

回到：目录 | 上一页：非捕获分组 | 下一页：独立表达式

预搜索（令宽度断言）

判断当前位置的前后字符，是否符合指定的条件，但不匹配前后的字符。

说明

预搜索有向前和向后两种：

表达式

方向

说明

(?=xxx)

正向预搜索（向右）

正向预搜索，判断当前位置右侧是否能匹配指定表达式

(?!xxx)

正向预搜索否定，判断当前位置右侧是否不能够匹配指定表达式

(?<=xxx)

反向预搜索（向左）

反向预搜索，判断当前位置左侧是否能够匹配指定表达式

(?<!xxx)

反向预搜索否定，判断当前位置左侧是否不能够匹配指定表达式

在 DEELX 中，不管整个表达式是“普通模式”还是“从右向左”模式，正向预搜索内部的表达式，始终采用“普通模式（从左向右）”模式，反向预搜索内部的表达式，始终采用“从右向左”模式。

“正向预搜索”在各个引擎中的表现基本一致。

关于“反向预搜索”中包含的表达式，Perl, Java, GRETA 以及 DEELX 的细节都不相同：

引擎

说明

举例

Perl

只能使用固定长度的反向预搜索。

(?<=\t)print

Java

允许使用不定长度的反向预搜索，但必须要有最大长度。

(?<=\{\s{0,100})print

GRETA

允许使用没有长度限制，但否定格式存在一些问题。

(?<=\{\s*)print

DEELX 中的反向预搜索：

DEELX 采用 RIGHTTOLEFT 模式来匹配“反向预搜索”中的表达式。使反向预搜索与正向预搜索在逻辑上完全相同，而方向相反。因此，在 DEELX 中，反向预搜索与正向预搜索一样，没有长度限制。

比如，在 DEELX 引擎中：

文本

表达式

匹配结果

{print}

(?<!\{\s*)print

匹配失败

(?<=\{\s*)print

匹配成功


独立表达式

DEELX 正则表达式扩展语法：独立表达式

回到：目录 | 上一页：预搜索（零宽度断言） | 下一页：条件表达式

独立表达式 (?>pattern)

独立表达式所匹配的内容，与将它单独匹配时匹配的内容一致。不管之后的表达式是否匹配成功，独立表达式内部都不进行回退，都不会再次尝试匹配。

说明

相比之下，如果 pattern 不是位于独立表达式中，当后边的表达式匹配失败时，pattern 所包含的不定次数的表达式（?, +, {n,m}, ……）会尝试改变匹配次数，选择表达式（比如：a|b）也会尝试匹配另一个选项，再次进行匹配，以尽量使整个表达式能够匹配成功。


DEELX 正则表达式扩展语法：条件表达式

回到：目录 | 上一页：独立表达式 | 下一页：递归表达式

条件表达式

根据某个条件是否成立，来选择匹配 2 个可选表达式中的其中一个。

说明

可以用于条件表达式的条件有两种类型：

  1. 指定分组（group）是否进行了捕获。
  2. 文本中当前位置是否可以与指定表达式匹配。

条件表达式的格式及说明：

表达式

条件特点

条件说明

(?(1)yes|no)

条件为数字

分组1如果有捕获，则进行 yes 部分匹配，否则 no 部分

(?(?=a)aa|bbb)

条件为预搜索

如果当前位置右侧是 a，则进行匹配 aa，否则匹配 bbb

(?(xxx)aa|bbb)

不与分组命名吻合

如果不与任何分组命名吻合，则视为 (?=xxx) 相同

(?(name)yes|no)

与分组命名吻合

如果与某分组命名吻合，则视为判断该分组是否进行捕获

另外：

  1. 如果表达式为 RIGHTTOLEFT 模式，那么 (?(xxx)aa|bbb) 与 (?(?<=xxx)aa|bbb) 相同。
  2. 如果条件表达式只有一个选择项，那么这个选项是在条件成立时进行匹配。
  3. 如果条件表达式中，使用“|”进行分隔的选项多于2个，则只有第一个“|”被视为条件表达式选项分隔符。比如： (?(?=xxx)yes|no1|no2)，条件成立时，匹配 yes 部分，否则匹配 "no1|no2"。


递归表达式

DEELX 正则表达式扩展语法：递归表达式

回到：目录 | 上一页：条件表达式 | 下一页：匹配模式

递归表达式 (?R)

对另一部分子表达式的引用，而不是对其匹配结果的引用。当被引用的表达式包含自身，则形成递归引用。

说明

相对于 "反向引用" 来说，反向引用是在匹配过程中，对匹配到的字符串内容进行引用，而 "递归匹配" 是对表达式进行引用。举例说明：

表达式

等效的表达式1

等效的表达式2

可以匹配

(\w)(?1)

(\w)(\w)

ab

(?1)(\w(?2))(\d)

(?1)(\w(\d))(\d)

(\w(\d))(\w(\d))(\d)

a1b23

如果被引用的表达式又包含自身，则形成了递归引用。举例说明：

表达式

等效1

等效2

可以匹配

(\w(?1)?)

(\w(\w(?1)?)?)

(\w+)

ghjk5……

\(([^()]|(?R))*\)

\(([^()]|\(([^()]|(?R))*\))*\)

(a * (c + 2))

DEELX 支持的递归表达式格式有：

格式

说明

(?R)

对整个表达式的递归引用。

(?R1)，(?R2)

对指定分组的递归引用。

(?1)，(?2)

(?R<named>)

对指定命名分组的递归引用。

(?R'named')


匹配模式

DEELX 正则表达式匹配模式

回到：目录 | 上一页：递归表达式 | 下一页：替换

DEELX 匹配模式

DEELX 支持的匹配模式有：IgnoreCase, Singleline, Multiline, Global, RightToLeft, Extended 这 6 种模式以及它们的组合。

说明

IGNORECASE

匹配时忽略大小写。默认情况下，正则表达式是要区分大小写的。不管是否指定忽略大小写模式，字符类，比如 [A-Z] 是要区分大小写的。

SINGLELINE

使小数点 "." 可以匹配包含换行符（\n）在内的任意字符。默认情况下，小数点只匹配换行符以外的任意字符，不匹配换行符。

MULTILINE

使 ^ 符号除了能够匹配字符串开始位置外，还能匹配换行符（\n）之后的位置；使 $ 符号除了能够匹配字符串结束位置外，还能匹配换行符之前的位置。默认情况下， ^ 符号只能匹配字符串开始位置， $ 符号只能匹配字符串结束位置。

SINGLELINE 和 MULTILINE 虽然听起来相互矛盾，但却是作用在不同的地方。因此它们是可以组合使用的。

在指定了 MULTILINE 之后，如果需要仅匹配字符串开始和结束位置，可以使用 \A 和 \Z。

GLOBAL

使 \G 可以用来匹配本次查找匹配的开始位置，对于连续的匹配来说，也就是上次匹配的结束位置。默认情况下， \G 没有作用。

DEELX 在进行替换操作（Replace）时，不管是否指定 GLOBAL 模式，DEELX 都可以进行所有的替换。是否指定 GLOBAL 模式只是对 \G 起作用。如果希望进行有限次数的替换，可在替换操作时指定替换次数。

RIGHTTOLEFT

从右向左的进行匹配。从被匹配字符串的结束位置向前进行查找匹配，同时，在表达式中也是右侧的表达式先进行匹配。

表达式的写法仍然按原来的习惯：匹配次数修饰符（*, +, {n}, ……）仍然位于被修饰部分的右侧而不是左侧；^ 仍然匹配文本开始而不是文本结束；(?=xxx) 仍然是正向与搜索（向右预搜索），而不是向左；分组（group）编号仍然是从左向右进行编号；等等。

不管整个表达式是否指定了 RightToLeft 模式，"反向预搜索（反向零宽度断言）" 内的表达式始终采用 RightToLeft 模式。

EXTENDED

使 DEELX 忽略表达式中的空白字符，并且把从 # 开始到该行行末的内容视为注释。默认情况下，正则表达式中的空格，换行等字符将可以匹配相应的字符。指定了 EXTENDED 模式后，如果要在正则表达式中表示空白字符比如空格符号（space）时，应该用 \x20 表示，如果要在表达式中表示 # 符号，应该用 \# 表示。

不管是否指定了 EXTENDED 模式，括号内以 ?# 号开始时，比如(?# xxx )，那么这一对括号以及包含的内容都始终作为注释而被忽略。


替换语法

DEELX 正则表达式替换语法

回到：目录 | 上一页：匹配模式

Replace 替换操作

对匹配到的字符串进行替换操作。

说明

$1 ~ $999

代表某个捕获组捕获到的内容。如果捕获组编号大于表达式中的最大捕获组编号，那么 DEELX 会减少数字个数，以使捕获组编号小于或等于最大编号；而把剩余的数字看作字符串常量。

举例：

当前最大捕获组编号为 20，那么，指定替换为 "$999" 将被看作 "$9" + "99"；指定替换为 "$15" 将代表第 15 个捕获组。如果本来就是想把 "5" 当成字符串常量时（"$1" + "5"），可以使用 $0015 表示，DEELX 最多识别 3 位 10 进制数字。

${name}

代表指定命名分组捕获到的内容。

$$

表示一个 $ 符号。

$&

代表每次匹配到内容。

$`

代表原字符串中，匹配到的内容之前的字符串。$` 中`符号就是键盘左上角"~"下边的那个符号。

$'

代表原字符串中，匹配到的内容之后的字符串。$' 中 ' 符号就是单引号。

$+

代表所有“有捕获”的分组中，编号最大的那个分组。

举例："aaa(b+)|ccc(b+)" 在匹配 "aaabbb" 时，虽然最大分组是第2个分组，但最大“有捕获”的是第1个分组，此时的 $+ 代表 $1 。

$_

代表被替换的整个字符串。"_" 是下划线。


编程帮助

DEELX 正则引擎编程帮助

C++ 环境下的正则表达式引擎，RegExLab 的研究开发项目。

概述

DEELX 的移植和使用非常简单，DEELX 的所有代码只有一个头文件（deelx.h），include 该头文件即可。

不需要为 DEELX 创建 project，也不需要添加任何 cpp 或者静态库 lib 文件。运行时，也不依赖专门的动态库。由于 deelx.h 已经直接包含到你的项目中，因此不会存在 Runtime Library 与主项目不同的问题，也不用担心会产生连接错误的问题。

目录
  1. CRegexpT 模板类
    1. 构造方法
    2. Compile 方法
    3. MatchExact 方法
    4. Match 方法
    5. GetNamedGroupNumber 属性
    6. PrepareMatch 方法
    7. Replace 方法
    8. ReleaseContext 方法
    9. ReleaseString 方法

  2. MatchResult 类
    1. IsMatched 属性
    2. GetStart 属性
    3. GetEnd 属性
    4. GetGroupStart 属性
    5. GetGroupEnd 属性
    6. MaxGroupNumber 属性

  3. CContext 类
参见

[ [image] 正则表达式语法] - 详细介绍 DEELX 支持的正则表达式语法。

[ [image] 表达式工具 Match Tracer] - 推荐使用正则表达式可视化编写及调试工具。


CRegexpT 模板类

回到：目录 | 下一页：构造方法

概述

CRegexpT 模板类是 DEELX 中最重要的类，负责编译正则表达式和进行匹配替换。

CRegexpT 对象内部只记录正则表达式编译的相关信息。除了构造方法和 Compile 方法外，其他的所有匹配和替换方法都没有对 CRegexpT 对象内部数据做任何更改。因此，这些匹配和替换方法都是线程安全的。

CRegexpT 可以应用于各种简单基类型。声明为：

template <class CHART> class CRegexpT;
成员方法

构造方法
    构造 CRegexp 对象，如果在使用构造方法时添加了参数，则构造方法将调用 Compile 方法。

Compile 方法
    编译正则表达式。CRegexp 对象需要先编译了正则表达式之后才能使用。

MatchExact 方法
    判断正则表达式是否能够从文本开始位置，刚好匹配到文本结束位置。

Match 方法
    在文本中查找匹配符合正则表达式的子字符串。

GetNamedGroupNumber 属性
    根据命名分组的名称，获取命名分组的编号。

PrepareMatch 方法
    创建一个匹配过程上下文对象，匹配时重复使用上下文对象可提高匹配效率。

Replace 方法
    在文本中将符合正则表达式的子字符串替换成另一字符串。

ReleaseContext 方法
    释放由 PrepareMatch 返回的匹配过程上下文对象。

ReleaseString 方法
    释放由 Replace 返回的字符串对象。

类声明
template <class CHART> class CRegexpT
{
public:
CRegexpT(
 const CHART * pattern = 0,
int flags = 0);

void Compile(
 const CHART * pattern,
int flags = 0);

public:
MatchResult MatchExact(
 const CHART * tstring) const;

MatchResult Match(
 const CHART * tstring,
int start = -1) const;

MatchResult Match(
CContext * pContext) const;

CContext * PrepareMatch(
 const CHART * tstring,
int start = -1) const;

CHART * Replace(
 const CHART * tstring,
const CHART * replaceto,
int start = -1,
int ntimes = -1) const;

int GetNamedGroupNumber(
 const CHART * group_name) const;

public:
static void ReleaseString(
 CHART * tstring );

static void ReleaseContext(
CContext * pContext);
};


CRegexpT 模板类 - 构造函数

CRegexpT::构造方法

回到：目录 | 上一页：CRegexpT 概述 | 下一页：Compile 方法

构造方法 CRegexpT::CRegexpT

CRegexpT();

CRegexpT(const CHART * pattern, int flag = NO_FLAG);

参数

pattern
    正则表达式，使用 \0 作为结束标志。

flag
    表达式匹配模式。

说明

第一种构造函数，将构造一个未编译的对象。后一种构造函数将调用 Compile 方法进行编译。

传入的字符串类型，应与本 CRegexpT <CHART> 类使用的基类型一致。


CRegexpT 模板类 - Compile 方法

CRegexpT::Compile 方法

回到：目录 | 上一页：构造方法 | 下一页：MatchExact 方法

编译 CRegexpT::Compile

void Compile(const CHART * pattern, int flags = NO_FLAG);

参数

pattern
    正则表达式，使用 \0 作为结束标志。

flag
    表达式匹配模式。

说明

根据正则表达式语法，对正则表达式文本进行编译。

传入的字符串类型，应与本 CRegexpT <CHART> 类使用的基类型一致。


CRegexpT 模板类 - MatchExact 方法

CRegexpT::MatchExact 方法

回到：目录 | 上一页：Compile 方法 | 下一页：Match 方法

刚好匹配 CRegexpT::MatchExact

MatchResult MatchExact(const CHART * tstring) const;

返回值

返回匹配结果 MatchResult 对象。

通过 MatchResult 对象，可以得知是否匹配成功。如果成功，通过 MatchResult 对象可以获取捕获信息。

参数

tstring
    进行匹配的字符串，使用 \0 作为结束标志。

说明

验证传入的文本是否刚好匹配正则表达式。

所谓刚好匹配，就是要求正则表达式从文本开始位置刚好匹配到文本结束位置。


CRegexpT 模板类 - Match 方法

CRegexpT::Match 方法

回到：目录 | 上一页：MatchExact 方法 | 下一页：GetNamedGroupNumber 属性

查找匹配 CRegexpT::Match

MatchResult Match(const CHART * tstring) const;

MatchResult Match(const CHART * tstring, int start) const;

MatchResult Match(CContext * pContext) const;

返回值

返回匹配结果 MatchResult 对象。

通过 MatchResult 对象，可以得知是否匹配成功。如果成功，通过 MatchResult 对象可以获取捕获信息。

参数

tstring
    进行匹配的字符串，使用 \0 作为结束标志。

start
    开始查找匹配的位置。

pContext
    从同一段文本中连续匹配时，使用同一个上下文对象。

说明

从文本中查找匹配符合表达式的子字符串。

第一种形式，Match 方法未指定开始位置，则根据当前匹配模式是否是 RIGHTTOLEFT 模式决定开始位置：如果是普通模式，则从 0 开始，向右查找；如果是 RIGHTTOLEFT 模式，则从字符串结束位置开始，向左查找。

第二种形式，Match 方法指定了开始位置，则从指定位置开始查找。

第三种形式，使用上下文对象，从上次匹配结束位置或者初始化位置开始查找匹配。


CRegexpT 模板类 - GetNamedGroupNumber 属性

CRegexpT::GetNamedGroupNumber 属性

回到：目录 | 上一页：Match 方法 | 下一页：PrepareMatch 方法

命名分组编号 CRegexpT::GetNamedGroupNumber

int GetNamedGroupNumber(const CHART * group_name) const;

返回值

返回命名分组的编号。如果返回值小于0，则表示没有该命名分组。

参数

group_name
    命名分组名。

说明

通过命名分组名，返回命名分组编号。


CRegexpT 模板类 - PrepareMatch 方法

CRegexpT::PrepareMatch 方法

回到：目录 | 上一页：GetNamedGroupNumber 属性 | 下一页：Replace 方法

匹配准备 CRegexpT::PrepareMatch

CContext * PrepareMatch(const CHART * tstring) const;

CContext * PrepareMatch(const CHART * tstring, int start) const;

返回值

经过初始化的查找匹配上下文对象，用来在 Match(CContext * pContext) 中使用。

参数

tstring
    进行匹配的字符串，使用 \0 作为结束标志。

start
    开始查找匹配的位置。

说明

初始化上下文对象，准备从文本中查找匹配符合表达式的子字符串。

第一种形式，PrepareMatch 方法未指定开始位置，则根据当前匹配模式是否是 RIGHTTOLEFT 模式决定开始位置：如果是普通模式，则从 0 开始，向右查找；如果是 RIGHTTOLEFT 模式，则从结束位置开始，向左查找。

第二种形式，PrepareMatch 方法指定了开始位置，则从指定为开始查找。


CRegexpT 模板类 - Replace 方法

CRegexpT::Replace 方法

回到：目录 | 上一页：PrepareMatch 方法 | 下一页：ReleaseContext 方法

替换 CRegexpT::Replace

CHART * Replace(const CHART * str, const CHART * rplto, int start = -1, int ntimes = -1) const;

返回值

替换后得到的新字符串。

这个新字符串是替换过程中分配的字符串，使用完毕后，需要调用 CRegexpT::ReleaseString 进行释放。

参数

str
    被进行替换的初始文本。

rplto
    “替换为”字符串，将匹配到的子字符串替换成 rplto 字符串。参见替换语法。

start
    进行查找替换的开始位置。默认(-1)表示根据是否是 RIGHTTOLEFT 自动决定开始位置。

ntimes
    指定进行替换的次数。默认(-1)表示替换所有匹配。

说明

进行文本替换操作。

替换返回的文本，使用完毕后需要进行释。


CRegexpT 模板类 - ReleaseContext 方法

CRegexpT::ReleaseContext 方法

回到：目录 | 上一页：Replace 方法 | 下一页：ReleaseString 方法

释放上下文对象 CRegexpT::ReleaseContext

static void ReleaseContext(CContext * pContext);

参数

pContext
    由 PrepareMatch 返回的上下文对象。

说明

释放由 PrepareMatch 返回的上下文对象。


CRegexpT 模板类 - ReleaseString 方法

CRegexpT::ReleaseString 方法

回到：目录 | 上一页：ReleaseContext 方法 | 下一页：MatchResult 类概述

释放字符串 CRegexpT::ReleaseString

static void ReleaseString(CHART * tstring);

参数

tstring
    由 Replace 返回的字符串。

说明

释放由 Replace 返回的字符串。

如果你想在自己的代码中释放这个字符串，请注意一下 DEELX 中分配该内存的方式，在 template CBufferT<ELT> 中。


MatchResult 类

回到：目录 | 上一页：ReleaseString 方法 | 下一页：IsMatched 属性

概述

MatchResult 类用来记录匹配结果。

MatchResult 对象中记录了所匹配到的字符串在整个文本中的位置，以及各个捕获组的位置。

要获取命名分组捕获的字符串，先通过 CRegexpT 类中的 GetNamedGroupNumber 属性 获取分组编号，然后通过 MatchResult 对象获取捕获组信息。

成员方法

IsMatched 属性
    判断是否匹配成功，返回非 0 值表示匹配成功。

GetStart 属性
    获取匹配到的子字符串开始位置，如果未匹配成功则返回一个负值。

GetEnd 属性
    获取匹配到的子字符串结束位置，如果未匹配成功则返回一个负值。

GetGroupStart 属性
    获取指定分组的开始位置，如果该分组未捕获或者未匹配成功，则返回一个负值。

GetGroupEnd 属性
    获取指定分组的结束位置，如果该分组未捕获或者未匹配成功，则返回一个负值。

MaxGroupNumber 属性
    返回表达式中最大的分组编号。

类声明
class MatchResult
{
public:
int IsMatched() const;

public:
int GetStart() const;
int GetEnd () const;

public:
int MaxGroupNumber() const;
int GetGroupStart(int nGroupNumber) const;
int GetGroupEnd (int nGroupNumber) const;
};


MatchResult 类 - IsMatched 属性

MatchResult::IsMatched 属性

回到：目录 | 上一页：MatchResult 类概述 | 下一页：GetStart 属性

是否匹配成功 MatchResult::IsMatched

int IsMatched() const;

返回值

返回非零值表示匹配成功，返回 0 表示匹配失败。

说明

获取是否匹配成功。


MatchResult 类 - GetStart 属性

MatchResult::GetStart 属性

回到：目录 | 上一页：IsMatched 属性 | 下一页：GetEnd 属性

获取开始位置 MatchResult::GetStart

int GetStart() const;

返回值

匹配成功后，获取所匹配到的子字符串的开始位置。如果匹配失败，则返回负值。

说明

获取匹配到的子字符串开始位置。


MatchResult 类 - GetEnd 属性

MatchResult::GetEnd 属性

回到：目录 | 上一页：GetStart 属性 | 下一页：GetGroupStart 属性

获取结束位置 MatchResult::GetEnd

int GetEnd() const;

返回值

匹配成功后，获取所匹配到的子字符串的结束位置。如果匹配失败，则返回负值。

说明

获取匹配到的子字符串结束位置。


MatchResult 类 - GetGroupStart 属性

MatchResult::GetGroupStart 属性

回到：目录 | 上一页：GetEnd 属性 | 下一页：GetGroupEnd 属性

获取分组开始位置 MatchResult::GetGroupStart

int GetGroupStart(int nGroupNumber) const;

返回值

返回指定分组捕获的字符串的开始位置。如果指定分组未捕获，则返回负值。

参数

nGroupNumber
    分组编号。

说明

获取指定分组捕获的字符串的开始位置。如果指定分组未捕获，或者整个表达式未匹配成功，则返回负值。


MatchResult 类 - GetGroupEnd 属性

MatchResult::GetGroupEnd 属性

回到：目录 | 上一页：GetGroupStart 属性 | 下一页：MaxGroupNumber 属性

获取分组结束位置 MatchResult::GetGroupEnd

int GetGroupEnd(int nGroupNumber) const;

返回值

返回指定分组捕获的字符串的结束位置。如果指定分组未捕获，则返回负值。

参数

nGroupNumber
    分组编号。

说明

获取指定分组捕获的字符串的结束位置。如果指定分组未捕获，或者整个表达式未匹配成功，则返回负值。


MatchResult 类 - MaxGroupNumber 属性

MatchResult::MaxGroupNumber 属性

回到：目录 | 上一页：GetGroupEnd 属性 | 下一页：CContext 类

最大分组编号 MatchResult::MaxGroupNumber

int MaxGroupNumber() const;

返回值

返回最大分组编号。

说明

获取正则表达式最大捕获组编号。


CContext 类

回到：目录 | 上一页：MaxGroupNumber 属性

概述

CContext 类中存放了匹配过程中的数据。

说明

当需要在同一段文本中多次连续匹配时，对同一个 CContext 对象多次匹配，可以节约系统资源。

先通过 PrepareMatch 方法初始化 CContext 对象，然后使用 Match(CContext * pContext) 方法进行匹配，使用完毕后，使用 ReleaseContext 方法释放 CContext 对象。


示例

DEELX 正则引擎编程示例

C++ 环境下的正则表达式引擎，RegExLab 的研究开发项目。

概述

本页演示了 DEELX 正则引擎的使用方法。

简单示例

判断数字
    判断一个字符串是否全由数字组成。

判断电子邮件
    判断一个字符串是否是一个合法的电子邮件地址。

查找注释
    在一段 C++ 源代码文本中，查找注释。

连续查找
    列举一段文本中所有的带小数的数字。


查找注释

DEELX 正则引擎编程示例：查找注释

在一段 C++ 源代码文本中，查找注释。

表达式

/\*((?!\*/).)*(\*/)?|//([^\x0A-\x0D\\]|\\.)*

方法

Match

代码
#include "deelx.h"

int find_remark(const char * string, int & start, int & end)
{
// declare
static CRegexpT <char> regexp("/\\*((?!\\*/).)*(\\*/)?|//([^\\x0A-\\x0D\\\\]|\\\\.)*");

// find and match
MatchResult result = regexp.Match(string);

// result
if( result.IsMatched() )
{
start = result.GetStart();
end = result.GetEnd ();
return 1;
}
else
{
return 0;
}
}

int main(int argc, char * argv[])
{
char * code1 = "int a; /* a */";
char * code2 = "int a;";

int start, end;

if( find_remark(code1, start, end) )
printf("In code1, found: %.*s\n", end - start, code1 + start);
else
printf("In code1, not found.\n");

if( find_remark(code2, start, end) )
printf("In code2, found: %.*s\n", end - start, code2 + start);
else
printf("In code2, not found.\n");

return 0;
}
说明

本例中的表达式，考虑了 C 注释（/*...*/）以及 C++ 注释（//...）。

但未排出注释标记位于字符串内部的情况。


电子邮件

DEELX 正则引擎编程示例：判断电子邮件

判断一个字符串是否是一个合法的电子邮件地址。

表达式

^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$

方法

MatchExact

代码
#include "deelx.h"

int test_email(const char * string)
{
// declare
static CRegexpT <char> regexp("^([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\\w]*[0-9a-zA-Z])*\\.)+[a-zA-Z]{2,9})$");

// test
MatchResult result = regexp.MatchExact(string);

// matched or not
return result.IsMatched();
}

int main(int argc, char * argv[])
{
char * str1 = "bob@smith.com";
char * str2 = "bob@.com";

printf("'%s' => %s\n", str1, (test_email(str1) ? "yes" : "no"));
printf("'%s' => %s\n", str2, (test_email(str2) ? "yes" : "no"));

return 0;
}


连续查找

DEELX 正则引擎编程示例：连续查找

列举一段文本中所有的带小数的数字。

表达式

\b\d+\.\d+

方法

Match

第一种代码
#include "deelx.h"

int main(int argc, char * argv[])
{
// text
char * text = "12.5, a1.1, 0.123, 178";

// declare
static CRegexpT <char> regexp("\\b\\d+\\.\\d+");

// loop
MatchResult result = regexp.Match(text);

while( result.IsMatched() )
{
printf("%.*s\n", result.GetEnd() - result.GetStart(), text + result.GetStart());

// get next
result = regexp.Match(text, result.GetEnd());
}

return 0;
}
第二种代码
#include "deelx.h"

int main(int argc, char * argv[])
{
// text
char * text = "12.5, a1.1, 0.123, 178";

// declare
static CRegexpT <char> regexp("\\b\\d+\\.\\d+");

// prepare
CContext * pContext = regexp.PrepareMatch(text);

// loop
MatchResult result = regexp.Match(pContext);

while( result.IsMatched() )
{
printf("%.*s\n", result.GetEnd() - result.GetStart(), text + result.GetStart());

// get next
result = regexp.Match(pContext);
}

// release
regexp.ReleaseContext(pContext);

return 0;
}


数字判断

DEELX 正则引擎编程示例：判断数字

判断一个字符串是否全由数字组成。

表达式

\d+

方法

MatchExact

代码
#include "deelx.h"

int test_all_number(const char * string)
{
// declare
static CRegexpT <char> regexp("\\d+");

// test
MatchResult result = regexp.MatchExact(string);

// matched or not
return result.IsMatched();
}

int main(int argc, char * argv[])
{
char * str1 = "12345";
char * str2 = "12345 abcde";

printf("'%s' => %s\n", str1, (test_all_number(str1) ? "yes" : "no"));
printf("'%s' => %s\n", str2, (test_all_number(str2) ? "yes" : "no"));

return 0;
}


下载

DEELX 下载（v1.2）

C++ 环境下的正则表达式引擎，RegExLab 的研究开发项目。

源代码下载

源代码只包含一个头文件。在你需要用 DEELX 的地方，直接 #include "deelx.h" 即可。

下载：

[ [image] 下载 DEELX 源文件] - 16kb

版权声明：

本免费软件，可以自由使用和转载发布。转载发布时必须声明原始出处为：
http://www.regexlab.com/deelx/

注意：

任何问题可通过 webmaster@regexlab.com 进行反馈。

[ [image] 参见：编程帮助]