2011-03-16 6 views
8

RegexBuddy에서 기대했던대로 동작하는 패턴을 만들었습니다. 그러나 적어도 TRegEx 또는 TPerlRegEx에 내장 된 최신 버전을 사용할 때는 Delphi XE로이 파일을 전송할 수 없습니다.Regex는 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

이것은 분명히 버그이므로보고해야합니다. – jachguate

답변

7

pcre_get_stringnumber이 이름을 찾지 못하면 PCRE_ERROR_NOSUBSTRING이 반환됩니다.

PCRE_ERROR_NOSUBSTRING은 정규 표현식 API에서 PCRE_ERROR_NOSUBSTRING = -7으로 정의됩니다.

일부 테스트는 보여줍니다 pcre_get_stringnumber 반환 kz 범위의 첫 글자를 가지고 있으며, 그 범위는 judge의 첫 글자의 의존하는 모든 이름에 대한 PCRE_ERROR_NOSUBSTRING. judge을 다른 것으로 변경하면 범위가 변경됩니다.

내가보기에 여기에 적어도 두 가지 버그가 있습니다. pcre_get_stringnumber의 하나는 버그는 PCRE 라이브러리를 래핑하거나 연결하는 PCRE OBJ 파일의 RegularExpressionsAPI 단위 것으로 보인다 대신 SRegExIndexOutOfBounds

+0

이 레벨의 문제를 파헤쳐 줘서 고마워. RegexBuddy의 저자 인 TPerlRegEx 라이브러리를 사용하여 해결책을 찾았습니다. 이 라이브러리는 XE의 구현을위한 기반을 형성하기 때문에 매우 다른 점이 있습니다. –

+0

+1, 좋은 발견. – jachguate

5

의 적절한 예외를 발생 할 필요가 TGroupCollection.GetItem 하나.

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 나는 uses 절에서 RegularExpressionsAPI을 제거하고 내 TPerlRegEx component에서 pcre 장치를 추가하는 경우 2 대신 1과 2

, 그때 제대로 수행 :이 코드를 실행하면 인쇄 1 및 2

델파이 XE의 RegularExpressionsAPI은 내 pcre 단위를 기반으로하고 RegularExpressionsCore 단위는 내 PerlRegEx 단위를 기반으로합니다. 엠바 카데로 (Ensarcadero)는 두 장치를 약간 변경했습니다. 그들은 또한 RegularExpressionsAPI에 의해 링크 된 자신의 OBJ 파일을 PCRE 라이브러리에서 컴파일했습니다.

나는 또한 존재하지 않는라는 이름의 그룹을 요청할 때 TGroupCollection.GetItem 좀 더 합리적인 예외를 발생하도록 요청하는 별도의 보고서 QC 92498을 만든 QC 92497

로이 버그를보고했다.(이 코드는 RegularExpressions 단위이며 Vincent Parrett이 작성한 코드를 기반으로합니다.