初めに
PerlやGrep等のスクリプト言語でおなじみの正規表現。文字列から特定の文字列を抽出・置換するのに便利です。そして、.NET Framework にも用意されているのです。つまり、Visual C++ でも使える!
以下、その紹介です。
正規表現で抽出する。
先ずは、文字列から正規表現を使って、特定の文字列を抽出する関数を記述してみましょう。
Matchメソッドを使います。
String^ matchRegex (String^ regex, String^ str) { String^ tmp = str; System::Text::RegularExpressions::Regex^ r; r = gcnew System::Text::RegularExpressions::Regex(regex); System::Text::RegularExpressions::Match^ m = r->Match(tmp); if (m->Success) return m->Value; else
return ""; }
regex :正規表現文字列(正規表現の構文はこちらからどうぞ) str :検索対象文字列 戻り値 :一致した文字列。一致しなかった場合は、"" が返る。
型指定が長ったらしいですが、正規表現エンジンへのアクセスを提供するクラス:
using namespace System::Text::RegularExpressions;
を記述しておけば、Regex や Match だけで記述できます。
使い方は、
matchRegex("[0-90-9]+", "2009年10月31日")
とすると、戻り値は、
"2009"
となります。
このように、この関数では、最初に一致したパターンしか返りません。一致した全ての文字列を返すには、Matchesメソッドを使う必要があります。
array <String^>^ matchesRegex (String^ regex, String^ str) { array <String^>^ tmp = {""}; System::Text::RegularExpressions::Regex^ r; r = gcnew System::Text::RegularExpressions::Regex(regex); System::Text::RegularExpressions::MatchCollection^ res = r->Matches(str); if (res->Count > 0) { tmp = gcnew array <String^>(res->Count); int i=0; for each (System::Text::RegularExpressions::Match^ m in res) tmp[i++] = m->Value; } return tmp; }
regex :正規表現文字列 str :検索対象文字列 戻り値 :一致した文字列アレイ 一致しなかった場合は、{""} ("" が一個だけの文字列アレイ)が返る。
Match オブジェクトの MatchCollection から文字列アレイを作り出すのに一手間かかっていますが、もっと簡単な方法があるのかもしれません。
使い方は、
matchesRegex("[0-90-9]+", "2009年10月31日")
とすると、戻り値は、
{"2009", "10", "31"}
となります。
正規表現で置換する。
さて、置換は戻り値が文字列なので関数も簡単になります。使うメソッドは、Replaceです。
String^ replaceRegex (String^ regex, String^ str, String^ replace) { System::Text::RegularExpressions::Regex^ r; r = gcnew System::Text::RegularExpressions::Regex(regex); return r->Replace(str, replace); }
regex :正規表現文字列 str :置換対象文字列 replace :置換文字列 戻り値 :置換した文字列 一致しなかった場合は、置換対象文字列そのままが返る。
使い方は、
matchesRegex("[0-90-9]+", "2009年10月31日", "")
とすると、戻り値は、
"年月日"
となります。置換文字列を "" にすれば、remove と同じですね。
replaceメソッドでは、正規表現と一致した文字列を使って置換文字列を生成する関数を指定することもできます。
String^ replaceDelegateRegex (String^ regex, String^ str, System::Text::RegularExpressions::MatchEvaluator^ replace) { System::Text::RegularExpressions::Regex^ r; r = gcnew System::Text::RegularExpressions::Regex(regex); eturn r->Replace(str, replace); }
regex :正規表現文字列 str :置換対象文字列 replace :正規表現と一致した文字列を使って置換文字列を生成する関数 戻り値 :置換した文字列 一致しなかった場合は、置換対象文字列そのままが返る。
使うには、先ず、正規表現と一致した文字列を使って置換文字列を生成する関数を用意する必要があります。
static String^ zenkaku2hankakuNumber(System::Text::RegularExpressions::Match^ m) { String^ zenkaku = m->Value; String^ tmp = ""; String^ hankaku = "0123456789"; array <Char>^ ca = zenkaku->ToCharArray(); int i = 0; for each (Char c in zenkaku) { unsigned int x = c; if ((x > 0xff0F) && (x < 0xff1A)) // '0'~'9'なら半角に変換 tmp = tmp + hankaku[x - 0xff10]; else tmp = tmp + zenkaku[i]; i++; } return tmp; }
m :Matchオブジェクト 戻り値 :置換した文字列。 一致しなかった場合は、置換対象文字列そのままが返る。
引数は、Matchオブジェクトで、戻り値が、文字列であることが必要のようです。
そして、static指定も必須です。
使い方は、
replaceDelegateRegex("[0-90-9]+", "2009年10月31日", gcnew System::Text::RegularExpressions::MatchEvaluator(&zenkaku2hankakuNumber))
こんな感じ。関数zenkaku2hankakuNumberは、全角数字を半角数字に変換しますので、
"2009年10月31日"
という具合に戻り値が得られます。
よく使うのはこんなところでしょうか。
これを使って何をするのか?それは、また別の機会に。
動作サンプルとソース(regextest.zip)は、こちらからどうぞ。動作サンプルとソースでは、Splitメソッドも使っています。
プログラム作製に使ったツールは、Visual C++ 2008 Express Edition 日本語版です。レジストリ等は使用していませんので、適当なフォルダに実行ファイル(RegexTest.exe)を解凍すれば使えます。なおプログラムの実行に際しては、以下のモジュールが必要です。必要に応じてインストールして下さい。
Microsoft .NET Framework Version 2.0 再頒布可能パッケージ (x86)
Microsoft .NET Framework 2.0 Service Pack 1 (x86)
Microsoft Visual C++ 2008 再頒布可能パッケージ (x86)
なお、掲載したソースおよび実行ファイルは、ご自由にお使い下さい。ただし、ご使用により、いかなる弊害や不具合が生じたとしても、当方ではいかなる責任も持ちません。予め、ご了承下さい。
Thinking-J
https://sites.google.com/site/thinkingj2007/home
mail : thinkingj.2007@gmail.com