C++で正規表現(vbscript.dll編) [プログラミング]
C++で正規表現を使います(その2)。
Windowsでは、VBScript用の正規表現を他のプログラムから利用できるようになっています。COMテクノロジを使うことで。
そのためには、いくつかの手順が必要です。
Visual Studio 付属のOLE Viewerで探すと、「Microsoft VBScript Regular Expressions」が見つかり、vbscript.dllで提供されていることが分かります。
そこで、以下の様にプログラムを書いてみます。
#import "vbscript.dll"
すると、正規表現を使うためのクラスが使用可能に………なりません。
何故に?
MSDNによれば、olb、tlb、dll が指定できると書いてあるのに……。
XMLは「#import "msxml.dll"
」で使えるようになるのに……。
そこで、あらためてOLE Viewerの画面を良く見てみると、ファイル名が「vbscript.dll\3
」となっています。
そんなファイルはもちろん存在せず、「#import "vbscript.dll\3"
」としてもエラーになります。
さて、#import
ディレクティブは、タイプライブラリを指定するものなのですが、どういう理屈でDLLを指定できるのかと言うと……
DLLのリソースにタイプライブラリの情報を持っていて、そのリソースを参照しているのです。
では、vbscript.dllではどうなっているのでしょう。
タイプライブラリのリソースが3つあります。
この3つ目が正規表現用のタイプライブラリなのですが(2つ目は古いバージョンの正規表現のタイプライブラリ情報)、#import
ディレクティブでは1つ目のものしか参照できないのです。
さて、能書きはココまでとして、実際にどうしたら正規表現を使えるようになるかの手順を書きます。
- OLE Viewerで「Microsoft VBScript Regular Expressions 5.5」をダブルクリックする。
- メニューから[File]-[Save As]を選択する。ファイル名を(例えば)"vbscript.idl"で保存する。
- コマンドプロンプトで
midl vbscript.IDL
と入力する。 - "vbscript.tbl"が出来上がる。
- ソースコードに「
#import "vbscript.tlb"
」と記述する。
これで、正規表現用のクラスが使えるようになります。
(何故かウチの環境ではIDLファイルの保存に失敗しましたが)
(いつからこの形式が使えるようになったのか分かりませんが)#import
ディレクティブにGUIDを指定出来るようになっているので、上の手順を踏むのが面倒な人は、次の書き方でもOKです。
#import "libid:3F4DACA7-160D-11D2-A8E9-00104B365C9F" version("5.5")
ココまでが前置きです。これで漸くコード本体に入れます。
::CoInitialize(NULL); { VBScript_RegExp_55::IRegExp2Ptr ex(__uuidof(VBScript_RegExp_55::RegExp)); ex->PutPattern(pattern); VBScript_RegExp_55::IMatchCollection2Ptr result_list = ex->Execute(target); for (long i = 0; i < result_list->GetCount(); i++) { VBScript_RegExp_55::IMatch2Ptr result = result_list->GetItem(i); std::cout << "pos = " << result->GetFirstIndex() << "\n" << "len = " << result->GetLength() << "\n" << "str = " << static_cast<const char*>(result->GetValue()) << "\n"; VBScript_RegExp_55::ISubMatchesPtr sub = result->GetSubMatches(); for (long j = 0; j < sub->GetCount(); j++) { std::cout << "sub = " << static_cast<const char*>(static_cast<_bstr_t>(sub->GetItem(j))) << "\n"; } } } ::CoUninitialize();
COMテクノロジを使うので、CoInitialize(), CoUninitialize()
が必要です。
Execute
は、パターンにマッチする部分を検索します。
文字列中のマッチする箇所を全て検索してしまうので、長い文字列から検索すると時間がかかるかも知れません。
他に、一致判定(Test
)と、置換(Replace
)があります。
日本語にも対応しています。
今日の一冊 | |
|
コメント 0