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".有保留的话我不能用吗?我不这么认为,因为在我的真实例子中,我尝试过完全随机的名字.我只是无法弄清楚导致这种行为的原因.
当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
该错误似乎在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编写的代码的单元中,而不是我自己.)