如何使用Delphi TRegEx替换特定的捕获组?

时间:2016-10-03 23:09:33

标签: regex delphi delphi-xe7

我试图在Delphi XE7中使用TRegex进行搜索并替换为字符串。

字符串看起来像这样“@FXXX(b,v,”,我想替换第二个整数值v。 例如:   @ F037(594,2027,-99,-99,0,0,0,0)

可能会成为   @ F037(594,佛瑞德,-99,-99,0,0,0,0)

我是RegEx的新手但是制作了这种模式似乎可以很好地找到匹配并为“2027”识别正确的捕获组(括号中的下面部分)。这是:

@F \ d {3}(\ S * \ d {1,5} \ S *,\ S *(\ d {1,5})\ S *,

我的问题是我无法解决如何使用Delphi TRegEx实现替换捕获的组“2027”。我对TMatch和TGroup以及如何使用它们感到相当困惑。有谁能建议一些示例代码?我也怀疑我不理解反向引用的概念。

这是我到目前为止所做的:

Uses
   RegularExpressions;

//The function that does the actual replacement
function TForm6.DoReplace(const Match: TMatch): string;
begin
  //This causes the whole match to be replaced.
  //@F037(594,2027,-99,-99,0,0,0,0) becomes  Fred-99,-99,0,0,0,0)
  //How to just replace the first matched group (ie 2027)?
  If Match.Success then
     Result := 'Fred';
end;


//Code to set off the regex replacement based on source text in Edit1 and put the result back into Memo1
//Edit1.text set to  @F037(594,2027,-99,-99,0,0,0,0)

procedure TForm6.Button1Click(Sender: TObject);

var
  regex: TRegEx;
  Pattern: string;
  Evaluator: TMatchEvaluator;

begin
  Memo1.Clear;
  Pattern := '@F\d{3}\(\s*\d{1,5}\s*,\s*(\d{1,5})\s*,';
  RegEx.Create(Pattern);
  Evaluator := DoReplace;
  Memo1.Lines.Add(RegEx.Replace(Edit1.Text, Pattern, Evaluator));
end;

1 个答案:

答案 0 :(得分:2)

使用正则表达式替换时,将替换整个匹配的内容。您可以访问整个匹配,捕获的组和命名的捕获组。

在Delphi中有两种不同的方法。

您当前正在使用Evaluator,这是一个包含要替换的指令的对象方法。在此方法中,您可以访问整个匹配内容。结果将是替换字符串。 如果vanilla正则表达式不能替换你想做的事情(例如增加数字,更改字符),这种方法很有用

还有另一种重载方法,它使用字符串作为替换。由于你想在这里做一个基本的正则表达式替换,我建议使用它。 在此字符串中,您可以反向引用匹配的模式(整个匹配为$0,捕获的组为$Number,命名捕获组为${Name},但也可以添加所需的任何字符。

因此,您可以捕获要保留在组中的所有内容,然后按照Wiktors注释中的建议进行反向引用。 当您进行单个替换时,我也建议使用类函数TRegex.Replace而不是创建正则表达式然后替换。

Memo1.Lines.Add(
  TRegex.Replace(
    Edit1.Text, 
    '(@F\d{3}\(\s*\d{1,5}\s*,\s*)\d{1,5}(\s*,)', 
    '$1Fred$2'));

PCRE正则表达式还支持\K(省略之前匹配的所有内容)和前瞻,可用于准确捕获您要替换的内容,例如

Memo1.Lines.Add(
  TRegex.Replace(
    Edit1.Text, 
    '@F\d{3}\(\s*\d{1,5}\s*,\s*\K\d{1,5}(?=\s*,)', 
    'Fred'));