7

我尝试使用 TPerlRegEx 类用新行替换空格。

with RegExp do
begin
  Subject:=Memo1.Lines.Text;
  RegEx:=' ';
  Replacement:='\r\n';
  ReplaceAll;
  Memo1.Lines.Text:=Subject;
end;

问题在于它将 \r\n 替换视为文字文本。

4

3 回答 3

8

利用#13#10

program Project29;

{$APPTYPE CONSOLE}

uses
  SysUtils, PerlRegEx;

var RegEx: TPerlRegEx;

function CStyleEscapes(const InputText:string):string;
var i,j: Integer;

begin
  SetLength(Result, Length(InputText));
  i := 1; // input cursor
  j := 1; // output cursor
  while i <= Length(InputText) do
    if InputText[i] = '\' then
      if i = Length(InputText) then
        begin
          // Eroneous quotation...
          Result[j] := '\';
          Inc(i);
          Inc(j);
        end
      else
        begin
          case InputText[i+1] of
            'r', 'R': Result[j] := #13;
            'n', 'N': Result[j] := #10;
            't', 'T': Result[j] := #9;
            '\':
              begin
                Result[j] := '\';
                Inc(j);
                Result[j] := '\';
              end;
            else
              begin
                Result[j] := '\';
                Inc(j);
                Result[j] := InputText[i+1];
              end;
          end;
          Inc(i,2);
          Inc(j);
        end
    else
      begin
        Result[j] := InputText[i];
        Inc(i);
        Inc(j);
      end;
  SetLength(Result, j-1);
end;

begin
  RegEx := TPerlRegEx.Create;
  try

    RegEx.RegEx := ' ';
    RegEx.Replacement := CStyleEscapes('\t\t\t');;
    RegEx.Subject := 'FirstLine SecondLine';
    RegEx.ReplaceAll;
    WriteLn(RegEx.Subject);

    ReadLn;

  finally RegEx.Free;
  end;
end.
于 2013-01-06T15:49:11.017 回答
6

我真的很想知道为什么它没有按预期进行匹配。

文本中\转义序列的处理在. 如果您查看代码,您会发现没有产生回车和换行字符的序列。实际上都是关于反向引用的。ReplacementTPerlRegEx.ComputeReplacementComputeReplacement

正则表达式的匹配阶段的处理由PCRE代码执行。但是,替换阶段是纯 Pascal 代码。并且很容易检查代码以了解它的作用。它不会按照您的想法和期望去做。

结论是您无法使用转义序列指定所需的字符。我认为您需要设计自己的规则来转义不可打印的字符并将这些规则应用到OnReplace事件处理程序中。

于 2013-01-06T18:00:25.803 回答
1

编辑,因为我今天学到了一些新东西。

我前一段时间遇到了与问题相同的问题,并得出了错误的结论
TRegEx根本不做任何 C 风格的反斜杠转义扩展.

正确的结论应该是在字符串参数
TRegEx中没有做C风格的反斜杠转义扩展replacement,我应该研究是否在pattern字符串参数中做。

我知道对字符转义机制的支持因开发工具而异

例如,C、C#、Java、Perl、PHP、Ruby、bash 等等都进行反斜杠转义扩展。
但是由于 Delphi 编译器(因为它不是 C 风格的编译器)没有。
它会将Pascal 样式的转义(如#13#10, 或^M^J)扩展为 CRLF。

所以我今天做了这项研究(感谢 David 指出我最初的错误),并提出了两个示例(一个在 Delphi 中一个在 C# 中),它们的功能基本上可以做到这一点:

  • 显示已知 CRLF 字符串的模式匹配结果,以及包含字符串的模式
  • 显示用字符串替换空格

然后通过以下方式调用示例函数:

  • 源代码中的字符串是反斜杠转义的 \r\n 字符串,因此可能会被编译器解析
  • 将字符放在一起的字符串,因此它成为反斜杠转义的 \r\n 字符串运行时可能会被 RegEx 引擎解析

从两个示例的输出中,您可以看到:

  • Delphi 编译器不解析 \r\n 字符串
  • C# 编译器会解析 \r\n 字符串
  • Delphi 和 C# 中的 RegEx 引擎在运行时解析模式 \r\n 字符串(RegEx 文档
  • Delphi 和 C# 中的 RegEx 引擎在运行时不解析替换 \r\n 字符串(RegEx 文档

建议仍然有效:

所以要么使用 Pascal 风格的转义,要么使用 Cosmin 写的C风格反斜杠扩展函数。

附带说明:使用任何扩展功能时,您应该记住它会改变文本的含义。Delphi 用户可能不会期望 C 风格的字符串扩展。

于 2013-01-07T08:22:09.817 回答