TPerlRegExクラスを使用して、スペースを新しい行に置き換えようとしています。
with RegExp do
begin
Subject:=Memo1.Lines.Text;
RegEx:=' ';
Replacement:='\r\n';
ReplaceAll;
Memo1.Lines.Text:=Subject;
end;
問題は、\ r\n置換をリテラルテキストとして扱うことです。
TPerlRegExクラスを使用して、スペースを新しい行に置き換えようとしています。
with RegExp do
begin
Subject:=Memo1.Lines.Text;
RegEx:=' ';
Replacement:='\r\n';
ReplaceAll;
Memo1.Lines.Text:=Subject;
end;
問題は、\ r\n置換をリテラルテキストとして扱うことです。
使用する#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.
なぜ期待通りにマッチングしないのか、本当に知りたかったです。
テキスト\
内のエスケープシーケンスの処理はで実行されます。コードを見ると、キャリッジリターンとラインフィードの文字を生成するシーケンスがないことがわかります。実際、すべてはバックリファレンスに関するものです。Replacement
TPerlRegEx.ComputeReplacement
ComputeReplacement
正規表現のマッチングフェーズの処理は、PCREコードによって実行されます。ただし、置換フェーズは純粋なPascalコードです。また、コードを調べてその機能を確認するのは簡単です。そして、それはあなたが考えていることや期待していることをしません。
結論として、エスケープシーケンスを使用して必要な文字を指定することはできません。OnReplace
印刷できない文字をエスケープするための独自のルールを考案し、それらのルールをイベントハンドラーに適用する必要があると思います。
今日、何か新しいことを学んだので、編集してください。
私はしばらく前の質問と同じ問題にぶつかり、間違った結論を出しました。
。TRegEx
Cスタイルのバックスラッシュエスケープ拡張はまったく行いません
正しい結論は、文字列パラメータでCスタイルのバックスラッシュエスケープ展開
TRegEx
を行わないということでした。文字列パラメータで行われるかどうかを調査する必要がありreplacement
pattern
ます。
文字エスケープメカニズムのサポートは、開発ツールによって異なることを私は知っていました。
たとえば、C、C#、Java、Perl、PHP、Ruby、bashなど、バックスラッシュエスケープ拡張を実行します。
しかし、Delphiコンパイラ(Cスタイルのコンパイラではないため)はそうではありません。ただし、 Pascalスタイルのエスケープ( 、、または)をCRLF
に拡張します。#13#10
^M^J
そこで、今日その調査を行い(最初の間違いを指摘してくれたDavidに感謝します)、基本的にこれを行う機能を持つ2つの例( 1つはDelphiで、もう1つはC#で)を考え出しました。
次に、サンプル関数は次のように呼び出されます。
両方の例の出力から、次のことがわかります。
RegEx
ドキュメント)RegEx
ドキュメント)推奨されるスタイルは次のとおりです。
したがって、Pascalスタイルのエスケープを使用するか、Cosminが記述したようなCスタイルのバックスラッシュ拡張関数を使用します。
補足:拡張機能を使用する場合は、テキストの意味が変わることに注意してください。Delphiユーザーは、文字列のCスタイルの拡張を期待しない場合があります。