8

RegexBuddy で、期待どおりに動作する一致パターンを作成しました。しかし、少なくとも組み込みの最新の TRegEx または TPerlRegEx を使用している場合、これを Delphi XE に転送することはできません。

私の実際のコードには 6 つのキャプチャ グループがありますが、より簡単な例で問題を説明できます。このコードは、最初のダイアログで "3" を返し、2 番目のダイアログの実行時に例外 (範囲外の -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;

しかし、キャプチャ グループを 1 つだけ使用すると、

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

最初のダイアログには「2」が表示され、2 番目のダイアログには予想どおり時刻「00:00」が表示されます。

ただし、名前付きキャプチャ グループが 1 つしか許可されていない場合、これは少し制限されますが、そうではありません...たとえば、キャプチャ グループ名を「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」が表示されます。使えない予約語はありますか?私の実際の例では、完全にランダムな名前を試したので、そうは思いません。この動作の原因がわかりません。

4

2 に答える 2

7

pcre_get_stringnumberが名前を見つけられない場合、がPCRE_ERROR_NOSUBSTRING返されます。

PCRE_ERROR_NOSUBSTRINGRegularExpressionsAPIではとして定義されていPCRE_ERROR_NOSUBSTRING = -7ます。

一部のテストでは、toの範囲に最初の文字があり、その範囲が。の最初の文字に依存しているすべての名前の戻り値が示されていpcre_get_stringnumberます。他のものに変更すると、範囲が変更されます。PCRE_ERROR_NOSUBSTRINGkzjudgejudge

私が見ているように、ここには少なくとも2つのバグが関係しています。TGroupCollection.GetItemに1つpcre_get_stringnumberあり、代わりに適切な例外を発生させる必要がありますSRegExIndexOutOfBounds

于 2011-03-16T10:09:31.667 に答える
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.

1 と 2 の代わりに -7 と 2 を出力します。

句から RegularExpressionsAPI を削除し、 TPerlRegEx コンポーネントからユニットusesを追加すると、1 と 2 が正しく出力されます。pcre

RegularExpressionsAPIDelphi XEのは私pcreのユニットに基づいており、RegularExpressionsCoreユニットは私のユニットに基づいていPerlRegExます。エンバカデロは両方のユニットにいくつかの変更を加えました。また、 によってリンクされている PCRE ライブラリから独自の OBJ ファイルをコンパイルしましたRegularExpressionsAPI

このバグをQC 92497として報告しました

また、別のレポートQC 92498を作成TGroupCollection.GetItemして、存在しない名前付きグループを要求したときに、より適切な例外を発生させるよう要求しました。(このコードは、RegularExpressions私ではなく Vincent Parrett によって書かれたコードに基づいたユニットにあります。)

于 2011-03-23T03:25:37.770 に答える