65.9K
CodeProject 正在变化。 阅读更多。
Home

DEELX - C++ 的正则表达式引擎

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (21投票s)

2006年10月11日

CPOL

3分钟阅读

viewsIcon

185280

downloadIcon

4498

DEELX 正则表达式引擎是最方便和最容易使用的引擎。

C++ 下载

Delphi 单元下载 (静态链接到 Delphi 项目)

下载 VB 的 ActiveX

下载动态链接版本

引言

DEELX 是一个用纯 C++ 编写的简单正则表达式引擎。

DEELX 的所有源代码只有一个头文件 (deelx.h)。无需任何其他 CPP 或 lib,当您想使用它时,无需单独为 DEELX 创建项目,也不必担心链接问题。

DEELX 具有良好的兼容性,可以由 Visual C++ 6.0、7.1、8.0 (Windows)、gcc(Cygwin)、gcc(Linux)、gcc(FreeBSD)、Turbo C++ 3.0(DOS)、C++ Builder(Windows) 等编译。DEELX 使用模板编码,因此charwchar_t 和其他简单类型可以用作其基本类型。

DEELX 正则表达式引擎是最方便和最容易使用的引擎。

特点

DEELX 支持 PERL 兼容的正则表达式语法。除了基本的模式语法外,DEELX 还实现了许多扩展语法

  • 从右到左匹配模式
  • 命名捕获组
  • 备注
  • 零宽度断言
  • 独立表达式
  • 条件表达式
  • 递归表达式
  • 替换操作

想法

DEELX 最重要的思想是“正则表达式元素”的概念。在源代码中,我称之为“ELX”。

我将每种元素视为“抽象元素”=>“ElxInterface”。这个 ElxInterface 有两个方法:Match()MatchNext()Match() 意味着尝试第一次匹配。如果 Match() 返回 true,但匹配到的不是您想要的,调用 MatchNext() 意味着放弃结果并尝试获得另一个成功的匹配。如果结果仍然不是您想要的,请继续调用 MatchNext() 直到它返回 false 或者您得到您想要的。

例如,两个元素:(.*)(a)

  1. 调用第一个元素 (.*) 的 "Match()" 方法将使其匹配所有文本。但是现在第二个元素 (a) 将无法匹配,因此先前 "Match()" 的匹配结果不是我想要的。
  2. 下一步是调用第一个元素 (.*) 的 "MatchNext()" 方法。此步骤也称为“backtrack”(回溯)。第一个元素 (.*) 将减少其重复次数,然后第二个元素 (a) 将再次尝试匹配。
  3. 因此,一种可能的最终结果是:即使第一个元素 (.*) 减少到零次,第二个元素仍然无法匹配,因此整个正则表达式未能匹配。
  4. 另一种最终结果是:当第一个元素 (.*) 减少到一定次数时,第二个元素成功匹配,因此整个正则表达式成功。

各种元素的匹配操作可以抽象为 "Match()" 和 "MatchNext()" 操作。

这就是 DEELX 的思想。

C++ 示例

#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+", IGNORECASE | MULTILINE);

    // 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;
}

正则表达式标志定义

 enum REGEX_FLAGS
 {
  NO_FLAG        = 0,
  SINGLELINE     = 0x01,
  MULTILINE      = 0x02,
  GLOBAL         = 0x04,
  IGNORECASE     = 0x08,
  RIGHTTOLEFT    = 0x10,
  EXTENDED       = 0x20,
 };

Delphi 封装 (静态链接到 Delphi 项目)

使用 Borland C++ Builder 将 DEELX 编译为 .obj 文件,然后将此 .obj 文件链接到 Delphi 单元:DEELX.dcu

uses
  DEELX;

var
  result:TMatchResult;
  re:TRegexpA;

begin
  result := TMatchResult.Create();
  re := TRegexpA.Create(Edit1.Text, IGNORECASE + MULTILINE); // the 2nd is 'FLAG's

  re.Match(Edit2.Text, result);

  if result.IsMatched() then
  begin
    Edit2.SelStart := result.GetStart();
    Edit2.SelLength := result.GetEnd() - result.GetStart();
  end
  else
  begin
    Edit2.SelLength := 0;
  end;

  re.Destroy;
  result.Destroy;
end;

正则表达式标志定义

const
  NO_FLAG        = $00;
  SINGLELINE     = $01;
  MULTILINE      = $02;
  GLOBAL         = $04;
  IGNORECASE     = $08;
  RIGHTTOLEFT    = $10;
  EXTENDED       = $20;

为 VB 封装到 ActiveX

将 DEELX 封装到 ActiveX 插件,以便 DEELX 可以在 VB 或 ASP 文件中使用。

Private pos As Integer
Private re As New RegExLab.RegExp

Private Sub Command1_Click()
    re.Compile (Text1.Text, "igm") ' the 2nd parameter is 'FLAG's

    re.Match Text2.Text, pos

    If re.IsMatched Then
        pos = re.End
        Text2.SelStart = re.Begin
        Text2.SelLength = re.End - re.Begin
    Else
        pos = -1
        Text2.SelLength = 0
    End If
End Sub

标志与 JScript.Regexp 相同

  s  -  SINGLELINE
  m  -  MULTILINE
  g  -  GLOBAL
  i  -  IGNORECASE
  r  -  RIGHTTOLEFT
  x  -  EXTENDED

DEELX 的 DLL 版本

deelx 的 DLL 版本为每个函数使用 stdcall 格式,因为 Visual Basic 只能调用 stdcall。

demo.zip 包含两个项目:一个是 Visual Basic,另一个是 Delphi。

参考和致谢

主页 - 我是作者,这是 DEELX 的主页。

© . All rights reserved.