Delphiにおける正規表現の実装と応用

利用するユニット:

uses  
  System.RegularExpressions;

1. TRegEx.Matchメソッドの利用

Match()メソッドは、条件に一致する最初の要素のみを取得し、他の一致要素の存在に関わらず動作します。

このメソッドはMatchオブジェクトを返却し、一致に関する詳細情報を保持しています。

Match()メソッドの基本的な使用法:

var
  foundMatch: TMatch;
begin
  foundMatch := TRegEx.Match('x9y8z7', '\\d');
  ShowMessage(foundMatch.Groups.Items[0].Value); // 最初の一致のみ取得可能。一致がない場合は無効値となる。

条件に一致する要素が一つだけ存在すると確信できる場合や、最初の一致結果のみが必要な場合にMatch()メソッドを使用します。

TMatchのMoveToNextメソッドで次の一致文字列を取得できます:
foundMatch := foundMatch.MoveToNext;

Groupsプロパティを使用してグループ化された正規表現との一致文字列を取得できます。

var  
  currentMatch: TMatch;  
  currentGroup: TGroup;  
begin  
  currentMatch := TRegEx.Match('2023/12/25', '(\\d+)/(\\d+)/(\\d+)');  
  ShowMessage(IntToStr(currentMatch.Groups.Count)); //=> 4

  for currentGroup in currentMatch.Groups do  
  begin  
    ShowMessage(Format('%s (%d, %d)',  
      [currentGroup.Value, currentGroup.Index, currentGroup.Length]));  
  end;  
  (* 結果表示
   2023/12/25 (1, 10)
   2023 (1, 4)
   12 (6, 2)
   25 (9, 2)
  *)

2. TRegEx.IsMatchメソッドの機能

IsMatch()メソッドは、条件に一致する要素が存在するかを判定し、真偽値を返します。

TRegEx.IsMatch('xyz123', '\\d'); // 数字が含まれるためtrueを返す
TRegEx.IsMatch('xyzabc', '\\w'); // 英数字が含まれるためtrueを返す

3. TRegEx.Matchesメソッドによる全一致取得

Matches()メソッドは、一致コレクションオブジェクトを取得します。このコレクションには、すべての正規表現一致結果を格納したMatchオブジェクトが含まれます。

TRegEx.Matchの宣言形式:

resultMatch: TMatch;

TRegEx.Matchesの宣言形式:

allMatches: TMatchCollection;

すべての一致結果を取得する必要がある場合、Matches()メソッドを使用します。

procedure TForm1.ButtonExecuteClick(Sender: TObject);  
var  
  collection: TMatchCollection;  
  expression, targetStr: string;  
  counter: Integer;  
begin  
  expression := InputEdit.Text; // 正規表現パターン  
  targetStr := SourceMemo.Text;  
  if TRegEx.IsMatch(targetStr, expression) then  
  begin  
    if CaseSensitiveBox.Checked then  
      collection := TRegEx.Matches(targetStr, expression, [roMultiLine]) 
    else  
      collection := TRegEx.Matches(targetStr, expression, [roIgnoreCase]); 
    ResultList.Clear;  
    for counter := 0 to collection.Count - 1 do  
    begin  
      ResultList.Add(collection.Items[counter].Value);  
    end;  
  end;  
end;
var  
  singleMatch: TMatch;  
  allResults: TMatchCollection;  
begin  
  allResults := TRegEx.Matches('Pascal Programming', '[A-Z]+');  
  ShowMessage(IntToStr(allResults.Count));

  singleMatch := allResults.Items[0];  
  ShowMessage(  
    Format('%s (%d, %d)',  
      [singleMatch.Value, singleMatch.Index, singleMatch.Length])); //=> P (1, 1)

  singleMatch := allResults.Items[1];  
  ShowMessage(  
    Format('%s (%d, %d)',  
      [singleMatch.Value, singleMatch.Index, singleMatch.Length])); //=> P (9, 1)

Matchesメソッドはfor-in構文に対応しています。

var  
  pattern: TRegEx;  
  element: TMatch;  
  results: TMatchCollection;  
begin  
  pattern := TRegEx.Create('[A-Z]+');  
  results := pattern.Matches('Object Pascal');  
  ShowMessage(IntToStr(results.Count));

  for element in results do  
    ShowMessage(  
      Format('%s (%d, %d)',  
        [element.Value, element.Index, element.Length]));

4. TRegEx.Replaceメソッドによる文字列置換
targetString := TRegEx.Replace('Object Pascal', '[A-Z]', '_'); //=> _bject _ascal

5. TRegEx.Split分割メソッドによる文字列分割

var  
  fragments: TArray<string>;  
  item: string;  
begin  
  fragments := TRegEx.Split('HTML CSS JavaScript', '[ ,]+');  
  for item in fragments do  
    OutputMemo.Lines.Add(item);

6. TRegEx.Escapeエスケープメソッドによる特殊文字処理

var
  escapedText: string;
begin
  escapedText := TRegEx.Escape('C#');
  ShowMessage(escapedText); //=> C\#

正規表現構文の検証

コンストラクタでroCompiledフラグが指定された場合、正規表現がコンパイルされます。
正規表現に問題がある場合、例外が発生します。

try
  TRegEx.Create(PatternInput.Text, [roCompiled]);
except on Error: Exception do
  ShowMessage(Error.Message);
end;

タグ: Delphi regex regular-expressions Pascal string-manipulation

8月16日 03:58 投稿