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接口。

在 JavaMatcher.group(0)中还返回整体正则表达式匹配。 Matcher.groupCount()返回不包括整体匹配的组数。大多数正则表达式库都是这样做的。

于 2013-07-17T13:13:36.450 回答