gpt4 book ai didi

regex - 使用 Delphi 的 TRegex 获取与结果匹配的捕获组

转载 作者:行者123 更新时间:2023-12-03 14:36:32 28 4
gpt4 key购买 nike

我编写了一个正则表达式,其作用是将所有匹配项返回到其三个备用捕获组。我的目标是了解每场比赛是哪个捕获组产生的。 PCRE 似乎能够产生该信息。但我还无法强制 Delphi XE8 中的 TRegEx 类来生成有意义的匹配捕获组信息。我不能声称自己是正则表达式类的负责人,而且 TRegEx 对我来说是新的,所以谁知道我犯了什么错误。

正则表达式 ( regex101.com workpad ) 是:

(?'word'\b[a-zA-Z]{3,}\b)|(?'id'\b\d{1,3}\b)|(?'course'\b[BL]\d{3}\b)

此测试文本:

externship L763 clinic 207 B706 b512

在测试环境中给出了五场比赛。但是,一个简单的测试程序遍历 TMatchCollection 中每个 TMatchTGroupCollection 显示了有关组的奇怪结果:所有匹配项都有多个组( 2、3 或 4),每个组的 Success 为 true,并且匹配的文本通常在多个组中重复或为空。所以这个数据结构(如下)不是我所期望的:

Using TRegEx
Regex: (?'word'\b[a-zA-Z]{3,}\b)|(?'id'\b\d{1,3}\b)|(?'course'\b[BL]\d{3}\b)
Text: externship L763 clinic 207 B706 b512

5 matches
'externship' with 2 groups:
length 10 at 1 value 'externship' (Sucess? True)
length 10 at 1 value 'externship' (Sucess? True)
'L763' with 4 groups:
length 4 at 12 value 'L763' (Sucess? True)
length 0 at 1 value '' (Sucess? True)
length 0 at 1 value '' (Sucess? True)
length 4 at 12 value 'L763' (Sucess? True)
'clinic' with 2 groups:
length 6 at 17 value 'clinic' (Sucess? True)
length 6 at 17 value 'clinic' (Sucess? True)
'207' with 3 groups:
length 3 at 24 value '207' (Sucess? True)
length 0 at 1 value '' (Sucess? True)
length 3 at 24 value '207' (Sucess? True)
'B706' with 4 groups:
length 4 at 28 value 'B706' (Sucess? True)
length 0 at 1 value '' (Sucess? True)
length 0 at 1 value '' (Sucess? True)
length 4 at 28 value 'B706' (Sucess? True)

我的简单测试运行程序是这样的:

program regex_tester;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.RegularExpressions,
System.RegularExpressionsCore;

var
Matched : Boolean;
J : integer;
Group : TGroup;
Match : TMatch;
Matches : TMatchCollection;
RegexText,
TestText : String;
RX : TRegEx;
RXPerl : TPerlRegEx;

begin
try
RegexText:='(?''word''\b[a-zA-Z]{3,}\b)|(?''id''\b\d{1,3}\b)|(?''course''\b[BL]\d{3}\b)';
TestText:='externship L763 clinic 207 B706 b512';

RX:=TRegex.Create(RegexText);

Matches:=RX.Matches(TestText);

Writeln(Format(#10#13#10#13'Using TRegEx'#10#13'Regex: %s'#10#13'Text: %s'#10#13,[RegexText, TestText]));

Writeln(Format('%d matches', [Matches.Count]));
for Match in Matches do
begin
Writeln(Format(' ''%s'' with %d groups:', [Match.Value,Match.Groups.Count]));

for Group in Match.Groups do
Writeln(Format(#9'length %d at %d value ''%s'' (Sucess? %s)', [Group.Length,Group.Index,Group.Value,BoolToStr(Group.Success, True)]));
end;

RXPerl:=TPerlRegEx.Create;
RXPerl.Subject:=TestText;
RXPerl.RegEx:=RegexText;

Writeln(Format(#10#13#10#13'Using TPerlRegEx'#10#13'Regex: %s'#10#13'Text: %s'#10#13,[RXPerl.Regex, RXPerl.Subject]));

Matched:=RXPerl.Match;
if Matched then
repeat
begin
Writeln(Format(' ''%s'' with %d groups:', [RXPerl.MatchedText,RXPerl.GroupCount]));
for J:=1 to RXPerl.GroupCount do
Writeln(Format(#9'length %d at %d, value ''%s''',[RXPerl.GroupLengths[J],RXPerl.GroupOffsets[J],RXPerl.Groups[J]]));

Matched:=RXPerl.MatchAgain;
end;
until Matched=false;

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

我当然希望能在正确的方向上有所插入。如果 TRegEx 被破坏,我当然可以使用替代方案 - 或者我可以放弃解决方案的优雅性,而是使用三个更简单的测试来查找我需要的信息。

添加信息和解释

正如 @andrei-galatyn 所说,TRegEx 使用 TPerlRegEx 进行工作。因此,我在测试程序中添加了一个部分(输出如下),我也在其中进行了实验。它使用起来不如 TRegEx 方便,但它的结果是它应该的样子,并且没有 TRegEx 损坏的 TGroup 数据结构的问题。无论我使用哪个类,最后一个组的索引(TRegEx 小于 1)就是我想要的捕获组。

一路上我被提醒,Pascal 数组通常基于 1 而不是 0。

Using TPerlRegEx
Regex: (?'word'\b[a-zA-Z]{3,}\b)|(?'id'\b\d{1,3}\b)|(?'course'\b[BL]\d{3}\b)
Text: externship L763 clinic 207 B706 b512

'externship' with 1 groups:
length 10 at 1, value 'externship'
'L763' with 3 groups:
length 0 at 1, value ''
length 0 at 1, value ''
length 4 at 12, value 'L763'
'clinic' with 1 groups:
length 6 at 17, value 'clinic'
'207' with 2 groups:
length 0 at 1, value ''
length 3 at 24, value '207'
'B706' with 3 groups:
length 0 at 1, value ''
length 0 at 1, value ''
length 4 at 28, value 'B706'

最佳答案

Delphi 内部使用 TPerlRegEx 类,它对 GroupCount 属性有这样的描述:

存储在组数组中的匹配组数。该数字是正则表达式中实际参与上一次匹配的编号最大的捕获组的编号。它可能小于正则表达式中捕获组的数量。

例如当正则表达式“(a)|(b)”匹配“a”时,GroupCount将为1。当相同的正则表达式匹配“b”时,GroupCount将为2。

TRegEx 类总是添加一组(我猜是为了整个表达式)。在你的情况下,检查每一个匹配应该就足够了:

case Match.Groups.Count-1 of
1: ; // "word" found
2: ; // "id" found
3: ; // "course" found
end;

它没有回答为什么群组中充满了奇怪的数据,实际上它似乎足以回答你的问题。 :)

关于regex - 使用 Delphi 的 TRegex 获取与结果匹配的捕获组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30804569/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com