Regex在Delphi XE中命名了捕获组

Ste*_*ten 8 regex delphi regexbuddy delphi-xe

我在RegexBuddy中构建了一个匹配模式,其行为完全符合我的预期.但我无法将其转移到Delphi XE,至少在使用最新的内置TRegEx或TPerlRegEx时.

我的真实世界代码有6个捕获组,但我可以用一个更简单的例子来说明问题.此代码在第一个对话框中显示"3",然后在执行第二个对话框时引发异常(-7索引超出范围).

var
  Regex: TRegEx;
  M: TMatch;
begin
  Regex := TRegEx.Create('(?P<time>\d{1,2}:\d{1,2})(?P<judge>.{1,3})');
  M := Regex.Match('00:00  X1 90  55KENNY BENNY');
  ShowMessage(IntToStr(M.Groups.Count));
  ShowMessage(M.Groups['time'].Value);
end;
Run Code Online (Sandbox Code Playgroud)

但是,如果我只使用一个捕获组

Regex := TRegEx.Create('(?P<time>\d{1,2}:\d{1,2})');
Run Code Online (Sandbox Code Playgroud)

第一个对话框显示"2",第二个对话框将按预期显示时间"00:00".

但是,如果只允许一个命名的捕获组,这将有点限制,但事实并非如此......如果我将捕获组名称更改为例如"atime".

var
  Regex: TRegEx;
  M: TMatch;
begin
  Regex := TRegEx.Create('(?P<atime>\d{1,2}:\d{1,2})(?P<judge>.{1,3})');
  M := Regex.Match('00:00  X1 90  55KENNY BENNY');
  ShowMessage(IntToStr(M.Groups.Count));
  ShowMessage(M.Groups['atime'].Value);
end;
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,我会得到"3"和"00:00".有保留的话我不能用吗?我不这么认为,因为在我的真实例子中,我尝试过完全随机的名字.我只是无法弄清楚导致这种行为的原因.

Mik*_*son 7

pcre_get_stringnumber找不到名称时,PCRE_ERROR_NOSUBSTRING返回.

PCRE_ERROR_NOSUBSTRING在RegularExpressionsAPI中定义为PCRE_ERROR_NOSUBSTRING = -7.

一些测试表明,每个名称的pcre_get_stringnumber返回值PCRE_ERROR_NOSUBSTRING在范围为kto z和该范围内的第一个字母取决于第一个字母judge.更改judge为其他内容会更改范围.

我看到它至少有两个错误.pcre_get_stringnumberTGroupCollection.GetItem中的一个和一个需要引发适当的异常而不是SRegExIndexOutOfBounds


Jan*_*rts 5

该错误似乎在RegularExpressionsAPI包装PCRE库的单元中,或者在它链接的PCRE OBJ文件中.如果我运行此代码:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, RegularExpressionsAPI;

var
  myregexp: Pointer;
  Error: PAnsiChar;
  ErrorOffset: Integer;
  Offsets: array[0..300] of Integer;
  OffsetCount, Group: Integer;

begin
  try
    myregexp := pcre_compile('(?P<time>\d{1,2}:\d{1,2})(?P<judge>.{1,3})', 0, @error, @erroroffset, nil);
    if (myregexp <> nil) then begin
      offsetcount := pcre_exec(myregexp, nil, '00:00  X1 90  55KENNY BENNY', Length('00:00  X1 90  55KENNY BENNY'), 0, 0, @offsets[0], High(Offsets));
      if (offsetcount > 0) then begin
        Group := pcre_get_stringnumber(myregexp, 'time');
        WriteLn(Group);
        Group := pcre_get_stringnumber(myregexp, 'judge');
        WriteLn(Group);
      end;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

它打印-7和2而不是1和2.

如果我从uses子句中删除RegularExpressionsAPI 并pcre从我的TPerlRegEx组件添加单元,那么它会正确打印1和2.

RegularExpressionsAPI德尔福XE是基于我对pcre单位和RegularExpressionsCore单位是基于我的PerlRegEx单位.Embarcadero确实对这两个单位做了一些改变.他们还从PCRE库中编译了自己的OBJ文件RegularExpressionsAPI.

我已将此错误报告为QC 92497

我还创建了一个单独的报告QC 92498,以请求TGroupCollection.GetItem在请求不存在的命名组时引发更明智的异常.(此代码位于RegularExpressions基于Vincent Parrett编写的代码的单元中,而不是我自己.)