C++Builder XEでSkRegExpを使って正規表現を使用する

Delphi用正規表現ライブラリ「SkRegExp」について調べました。

■SkRegExp

SkRegExpはDelphi 2005以降で使えるDelphi用正規表現ライブラリです。

Delphiで書かれていてDLLが不要なので手軽に使用でき、標準ライブラリのTRegExよりも高速で、日本語特有の処理に対応していて、ラインセスはMPL 1.1で利用できる、すばらしいライブラリです。

こちらのページからダウンロードできます。

■日本語特有の処理を行う

最初に、SkRegExpの特徴である日本語特有の処理を見てみましょう。

■■全角と半角を同一視して照合する

修飾子「k」はカタカナとひらがなを同一視して照合します。

var
  match: TMatch;
  matches: TMatchCollection;
begin
  matches := TRegEx.Matches('テスト、てすと', '(?k)テスト');

  for match in matches do
  begin
    Writeln(Format('%s (%d, %d)',[match.Value, match.Index, match.Length]))
  end;

実行結果

テスト (1, 3)
てすと (5, 3)

■■全角と半角を同一視して照合する

修飾子「w」は全角と半角を同一視して照合します。

var
  match: TMatch;
  matches: TMatchCollection;
begin
  matches := TRegEx.Matches('TEST、TEST、TEST', '(?w)TEST');

  for match in matches do
  begin
    Writeln(Format('%s (%d, %d)',[match.Value, match.Index, match.Length]))
  end;
end;

実行結果

TEST (1, 4)
TEST (6, 4)
TEST (11, 4)

■SkRegularExpressionsユニット

SkRegularExpressions.pasを使うと、TRegExと同じインターフェイスで使うことができます。
TRegExからの移行も簡単です。

SkRegularExpressionsユニットをincludeして使用します。

#include "SkRegularExpressions.hpp"

サンプルコードは「Delphi XEのTRegExで正規表現を使用する」とほとんど同じです。

■SkRegularExpressions.TRegEx.IsMatchメソッド 入力文字列に一致が存在するか

クラスメソッドを使う例

if (TRegEx::IsMatch("Delphi", "[A-Z]+"))
    ShowMessage("Match");

インスタンスメソッドを使う例

TRegEx regex("[A-Z]+");
if (regex.IsMatch("Delphi"))
  ShowMessage("Match");

■SkRegularExpressions.TRegEx.Matcheメソッド 正規表現に一致する最初の文字列を取得する

MatcheメソッドはTMatchレコードを返します。

クラスメソッドを使う例

TMatch match = TRegEx::Match("Delphi XE", "[A-Z]+");
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> D (1, 1)

インスタンスメソッドを使う例

TRegEx regex("[A-Z]+");
TMatch match = regex.Match("Delphi XE");
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> D (1, 1)

TMatchのNextMatchメソッドで次の一致した文字列を取得できます。

TRegEx regex("[A-Z]+");
TMatch match = regex.Match("Delphi XE");
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> D (1, 1)

//次の一致
match = match.NextMatch();
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> XE (8, 2)

TMatchのSuccessプロパティで一致したかどうかを調べることができます。

TRegEx regex("[A-Z]+");
TMatch match = regex.Match("Delphi XE");
while (match.Success)
{
  ShowMessage(match.Value);
  match = match.NextMatch();
}

グループ化した正規表現に一致した文字列は、TMatchのGroupsプロパティで取得できます。

TMatch match = TRegEx::Match("2012/5/14", "(\\d+)/(\\d+)/(\\d+)");
ShowMessage(match.Groups.Count); //=> 4

for (int i = 0; i< match.Groups.Count; ++i)
{
  Skregularexpressions::TGroup group = match.Groups[i];
  ShowMessage(Format("%s (%d, %d)",
    ARRAYOFCONST((group.Value, group.Index, group.Length))));
}

出力結果

2012/5/14 (1, 8)
2012 (1, 4)
5 (6, 1)
14 (8, 1)

■SkRegularExpressions.TRegEx.Matchesメソッド 正規表現に一致するすべての文字列を取得する

Matchesメソッドは、TMatchCollectionレコードを返します。

TMatchCollection matches = TRegEx::Matches("Delphi XE", "[A-Z]+");
ShowMessage(IntToStr(matches.Count));

TMatch match = matches.Item[0];
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> D (1, 1)

match = matches.Item[1];
ShowMessage(
  Format("%s (%d, %d)",
    ARRAYOFCONST((match.Value, match.Index, match.Length)))); //=> XE (8, 2)

■SkRegularExpressions.TRegEx.Replaceメソッド 正規表現に一致した文字列を置き換える

//アルファベットの大文字を_に置き換える
UnicodeString s = TRegEx::Replace("Delphi XE", "[A-Z]", "_");
ShowMessage(s); //=> _elphi __

引数に関数を渡すことで、マッチした文字にあわせて置換する文字を指定できます。

/* マッチした数値に1を加える */
UnicodeString __fastcall TForm1::IncNum(const TMatch& Match)
{
  TMatch m = Match;
  return IntToStr(StrToInt(m.Value) + 1);
}

//正規表現に一致した文字を関数処理して置き換える
UnicodeString s = TRegEx::Replace("Delphi 2009", "\\d+", IncNum);
ShowMessage(s); //=> Delphi 2010

■SkRegularExpressions.TRegEx.Splitメソッド 文字列を分割する

//半角スペースかスラッシュで分割する
Skregularexpressions::TStringDynArray splits = TRegEx::Split("Delphi C++Builder/RadPHP", "[ /]");
for (int i = 0; i < splits.Length; ++i)
  Memo1->Lines->Add(splits[i]);

■SkRegularExpressions.TRegEx.Escapeメソッド 特殊文字をエスケープする

UnicodeString s = TRegEx::Escape("C++");
ShowMessage(s); //=> C\+\+

■正規表現の文法を検証する

コンストラクタの引数にroCompiledを指定すると、正規表現をコンパイルします。
正規表現に問題があれば例外を投げます。

try {
  TRegEx regex("*", TRegExOptions() << roCompiled);
} catch (Exception &E) {
  ShowMessage(E.Message);
  //=>*...認識できない正規表現です; * <--
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください