德尔福TRegEx反向引用破坏了吗?

 高人arm 发布于 2023-02-06 09:12

我有一个问题TRegEx.replace:

var
  Value, Pattern, Replace: string;
begin
  Value   := 'my_replace_string(4)=my_replace_string(5)';
  Pattern := 'my_replace_string\((\d+)\)';
  Replace := 'new_value(\1)';
  Value   := TRegEx.Replace(Value, Pattern, Replace);
  ShowMessage(Value);
end;

new_value(4)=new_value(5)我的代码(用Delphi XE4编译)给出了预期的结果new_value(4)=new_value()1)

使用Notepad ++,我得到了预期的结果.

使用命名组可以清楚地看出1是字面意义上的后向引用:

Pattern := 'my_replace_string\((?\d+)\)';
Replace := 'new_value(${name})';
// Result: 'new_value(4)=new_value(){name})'

替换总是那么简单(可能是零次或多次my_replace_string),所以我可以轻松创建自定义搜索和替换功能,但我想知道这里发生了什么.

这是我的错,还是一个错误?

1 个回答
  • 我可以重现Delphi XE4中的错误.我在Delphi XE5中得到了正确的行为.

    这个bug就在TPerlRegEx.ComputeReplacement.我使用Delphi XE3为Embarcadero贡献的代码UTF8String.随着德尔福XE4 Embarcadero UTF8String从该RegularExpressionsCore单元中淘汰并取而代之TBytes.进行此更改的开发人员似乎错过了Delphi中字符串和动态数组之间的重要区别.字符串使用写时复制机制,而动态数组则不使用.

    因此,在我的原始代码中,TPerlRegEx.ComputeReplacement可以执行S := FReplacement然后修改临时变量S以替换反向引用而不影响FReplacement字段,因为两者都是字符串.在修改后的代码,S := FReplacement使得S指向相同的阵列FReplacement,并且当反向引用在S被取代时,FReplacement也被修改.因此,第一次更换是正确的,而后续更换是错误的,因为FReplacement已经瘫痪.

    在Delphi XE5中,通过替换S := FReplacement它来修复此问题以制作适当的临时副本:

    SetLength(S, Length(FReplacement));
    Move(FReplacement[0], S[0], Length(FReplacement));
    

    当Delphi 2009发布时,Embarcadero发表了很多关于不应该使用字符串类型来表示字节序列的讨论.现在看来他们正在犯下使用TBytes来表示字符串的相反错误.

    我之前向Embarcadero推荐的整个混乱的解决方案是切换到使用UTF16LE的新pcre16函数,就像Delphi字符串一样.当Delphi XE发布时,这些功能不存在,但它们现在已经存在,应该使用它们.

    2023-02-06 09:15 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有