2011-03-16 64 views
8

我在RegexBuddy中構建了一個匹配模式,其行爲與我預期的完全相同。但是我不能將它傳輸到Delphi XE,至少在使用最新內置的TRegEx或TPerlRegEx時。正則表達式在Delphi中命名捕獲組XE

我的現實世界的代碼有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; 

但是,如果我只用一個捕獲組

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

第一個對話框顯示「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; 

正如預期的那樣,我會得到「3」和「00:00」。是否有保留字我不能使用?我不這麼認爲,因爲在我的真實例子中,我嘗試了完全隨機的名字。我只是不知道是什麼原因導致了這種行爲。

+0

你應當QC,報告爲這顯然是一個錯誤。 – jachguate 2011-03-16 16:16:34

回答

7

pcre_get_stringnumber找不到名稱時,返回PCRE_ERROR_NOSUBSTRING

PCRE_ERROR_NOSUBSTRING在RegularExpressionsAPI中定義爲PCRE_ERROR_NOSUBSTRING = -7

一些測試表明,pcre_get_stringnumber回報PCRE_ERROR_NOSUBSTRING對於具有在kz範圍內的第一個字母和範圍取決於在judge的第一個字母的每一個名字。將judge更改爲其他內容會更改範圍。

正如我所看到的,這裏至少有兩個錯誤。一個在pcre_get_stringnumber,一個在TGroupCollection.GetItem需要提出一個適當的異常,而不是SRegExIndexOutOfBounds

+0

非常感謝挖的問題到這個水平。我找到了一個使用RegexBuddy作者的TPerlRegEx庫的解決方案解決方案。這個庫,按我的理解,形成了XE的實現基礎,所以我覺得差異非常神祕。 – 2011-03-16 10:34:02

+0

+1,發現不錯。 – jachguate 2011-03-16 16:16:51

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. 

它打印-7和1和2

2而不是如果我從uses子句除去RegularExpressionsAPI和從我TPerlRegEx component添加pcre單元,那麼它正確地做打印1和2

在Delphi XE的RegularExpressionsAPI基於我的pcre單元上,並且RegularExpressionsCore單元基於我的PerlRegEx單元上。 Embarcadero確實對這兩個單位做了一些改變。他們還通過RegularExpressionsAPI鏈接編譯自己的PCRE庫中的OBJ文件。

我已經報告這個錯誤作爲QC 92497

我還創建了一個單獨的報告QC 92498來請求TGroupCollection.GetItem請求不存在的命名組時,提出一個更明智的例外。(此代碼是在RegularExpressions單元,其基於由文森特Parrett,不是我自己寫的代碼。)