4

Apache Commonsライブラリからいくつかのクラスを移植していますが、次の動作がおかしいことがわかりました。次のように定義された正規表現があります

const
    IPV4_REGEX = '^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$';

そして私はそれを次のように使用します:

ipv4Validator: TRegEx; 

ipv4Validator := TRegEx.Create(IPV4_REGEX);

これを使用してIPアドレスを照合すると、次のコードはfalseを返します。デバッガーMatch.Groups.Countは5であることを示していますが、これは予期していませんでした。

var
  Match: TMatch;
begin
  Match := ipv4Validator.Match(inet4Address);

  if Match.Groups.Count <> 4 then
      Exit(false);

これはTMatch.Groups.Countの正しい動作ですか?


念のため、これが私のクラスの完全なコードです。テストが失敗したため、問題のある行にコメントしたことに注意してください。

unit InetAddressValidator;

interface

uses RegularExpressions;

const
  IPV4_REGEX = '^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$';

type

  TInetAddressValidator = class
  private
    ipv4Validator: TRegEx;
  public
    constructor Create; overload;
    function isValid(const inetAddress: String): Boolean;
    function isValidInet4Address(const inet4Address: String): Boolean;
  end;

implementation

uses SysUtils;

constructor TInetAddressValidator.Create;
begin
  inherited;
  ipv4Validator := TRegEx.Create(IPV4_REGEX);
end;

function TInetAddressValidator.isValid(const inetAddress: String): Boolean;
begin
  Result := isValidInet4Address(inetAddress);
end;

function TInetAddressValidator.isValidInet4Address(const inet4Address
  : String): Boolean;
var
  Match: TMatch;
  IpSegment: Integer;
  i: Integer;
begin
  Match := ipv4Validator.Match(inet4Address);

  // if Match.Groups.Count <> 4 then
  // Exit(false);

  IpSegment := 0;
  for i := 1 to Match.Groups.Count - 1 do
  begin
    try
      IpSegment := StrToInt(Match.Groups[i].Value);
    except
      Exit(false);
    end;

    if IpSegment > 255 then
      Exit(false);
  end;
  Result := true;
end;

end.
4

2 に答える 2

4

Match.Groups [0]には式全体が含まれているため、これは正しいです。

TGroupcollectionコンストラクター:

constructor TGroupCollection.Create(ARegEx: TPerlRegEx;
  const AValue: UTF8String; AIndex, ALength: Integer; ASuccess: Boolean);
var
  I: Integer;
begin
  FRegEx := ARegEx;
  /// populate collection;
  if ASuccess then
  begin
    SetLength(FList, FRegEx.GroupCount + 1);
    for I := 0 to Length(FList) - 1 do
      FList[I] := TGroup.Create(AValue, FRegEx.GroupOffsets[I], FRegEx.GroupLengths[I], ASuccess);
  end;
end;

ご覧のとおり、内部Flist(TArray<TGroup>)はグループ数+1で開始されます。FList[0]は、オフセット1と式全体の長さを持つグループを受け取ります。この動作は文書化されていません。

于 2013-03-12T14:08:25.717 に答える
1

DelphiTRegExは、.NETのRegexクラスを模倣するように設計されており、全体的な正規表現の一致もに追加されMatch.Groups.Countます。.NETは、GroupCollectionクラスがインターフェイスを実装できるようにこれを行いICollectionます。

JavaではMatcher.group(0)、全体的な正規表現の一致も返します。 Matcher.groupCount()全体の一致を除いたグループの数を返します。ほとんどの正規表現ライブラリはこの方法でそれを行います。

于 2013-07-17T13:13:36.450 に答える