正则表达式和TMatch.Groups.Count

时间:2013-03-12 13:26:41

标签: regex delphi delphi-xe

我正在从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.

2 个答案:

答案 0 :(得分: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和整个表达式长度的组。此行为未记录。

答案 1 :(得分:1)

Delphi的TRegEx旨在模仿.NET的Regex类,它还将整体正则表达式匹配添加到Match.Groups.Count。 .NET执行此操作以便GroupCollection类可以实现ICollection接口。

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