【问题标题】:How to Use Delphi TRegEx to replace a particular capture group?如何使用 Delphi TRegEx 替换特定的捕获组?
【发布时间】:2016-10-03 23:09:33
【问题描述】:

我正在尝试在 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;

【问题讨论】:

  • 捕获您需要保留的部分,并在替换模式中使用对它们的反向引用。只匹配(而不是捕获)您需要删除的内容。试试(@F\d{3}\(\s*\d{1,5}\s*,\s*)\d{1,5}(\s*,) pattern and replace with \1Fred\2
  • 谢谢 - 我认为我的主要问题是如何在 Delphi 代码中实现。 Delphi 文档中没有太多内容。您能对此提供任何指导吗?
  • @CHEAPS TRegex 有一个不使用 TMatchEvaluator 的重载替换方法,而是一个用于替换的模式(字符串)。您可能希望将其与 Wiktor 给出的模式一起使用。

标签: regex delphi delphi-xe7


【解决方案1】:

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

在 Delphi 中有两种不同的方法可以做到这一点。

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

还有另一个重载 Replace 方法,它使用字符串作为替换。由于您想在这里进行基本的正则表达式替换,我建议您使用它。 在此字符串中,您可以反向引用匹配的模式($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'));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-13
    • 2011-04-26
    • 2020-04-27
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多