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);
//=>*...認識できない正規表現です; * <--
}