[技術学習]ATL CAtlRegExp,GRETA,Boost::regexの3種類の正規表現ライブラリの概要


本文の要旨はいくつかの文章の内容を翻訳して、簡単にATL CAtlRegExp、GRETA、Boost::regexなどの正規表現ライブラリを紹介して、これらの表現ライブラリは私たちに正規ライブラリの巨大な威力を便利に利用することができて、私たちの仕事に便利を提供しました.
正規表現構文
ワードシンボル
意味
.
1文字の一致
[ ]
角カッコ内の任意の文字に一致する文字クラスを指定します.例:[abc]は「a」、「b」または「c」に一致する.
^
^が文字クラスの先頭に表示されると、文字クラスが否定され、この否定された文字クラスは角カッコ内の文字を除いた文字に一致します.たとえば、[^abc]は、「a」、「b」、および「c」以外の文字に一致します.^が正規表現の前に表示される場合、入力の先頭に一致します.例:^[abc]は、「a」、「b」または「c」で始まる入力に一致します.
-
「文字クラス」で、文字の範囲を指定します.たとえば、[0-9]は0から9の数字に一致します.
?
指定?前の式はオプションで、1回または一致しないことができます.例:[0-9][0-9]?「2」または「12」に一致します.
+
指定?前の式は1回または複数回一致します.たとえば、[0-9]+は「1」、「13」、「666」などと一致します.
*
*前の式が0回または複数回一致することを示します.
??, +?, *?
?, +*の非貪欲なマッチングバージョンと、できるだけ少ない文字にマッチングします.で、+と*は欲張りバージョンで、できるだけ多くの文字に一致します.たとえば、「」と入力すると、<.*?>「」と一致し、<.*>「」と一致します.
( )
グループ化オペレータ.たとえば、(/d+、)*/d+は、「1」または「1,23456」などのカンマで区切られた一連の数字に一致します.
/
エスケープ文字.たとえば、[0-9]+は1つまたは複数の数字に一致し、[0-9]/+は1つの数字に一致した後にプラス記号に従う場合.逆スラッシュ/は略語を表す場合にも使用され、/aは任意の数字、アルファベットを表す.後に1つの数字nが続くと、n番目の一致グループ(0から始まる)に一致します.たとえば、<{.*?}>.*?一致"Contents".なお、C++文字列では、「//+」、「//a」、「<{.*?}>.*?".
$
正規表現の最後に置いて、入力の末端に一致します.たとえば、[0-9]$は入力の最後の数字に一致します.
|
間隔記号は、2つの式を区切って、T|theが「The」または「the」に一致するように正確に一致します.
 
省略一致
略語
マッチ
/a
アルファベット、数字([a-zA-Z 0-9])
/b
スペース(blank):([//t])
/c
アルファベット([a-zA-Z])
/d
10進数([0-9])
/h
16進数([0-9 a-fA-F])
/n
改行:(/r|(/r?/n))
/q
参照文字列(/"[^/"]*/")|(/''''[^/''''']*/''')
/w
一段文字([a-zA-Z]+)
/z
整数([0-9]+)
ATL CATLRegExp ATL Serverでは、アドレスやコマンドなどの複雑な文字フィールド情報を復号する必要があることが多いが、正規表現は強力な文字解析ツールであるため、ATLは正規表現解釈ツールを提供している.例:
#include "stdafx.h"
#include <atlrx.h>
int main(int argc, char* argv[])
{
   CAtlRegExp<> reUrl;
   // five match groups: scheme, authority, path, query, fragment
   REParseError status = reUrl.Parse(
        "({[^:/?#]+}:)?(//{[^/?#]*})?{[^?#]*}(?{[^#]*})?(#{.*})?" );
   if (REPARSE_ERROR_OK != status)
   {
      // Unexpected error.
      return 0;
   }

   CAtlREMatchContext<> mcUrl;
   if (!reUrl.Match(
   "http://search.microsoft.com/us/Search.asp?qu=atl&boolean=ALL#results",
      &mcUrl))
   {
      // Unexpected error.
      return 0;
   }

   for (UINT nGroupIndex = 0; nGroupIndex < mcUrl.m_uNumGroups;
        ++nGroupIndex)
   {
      const CAtlREMatchContext<>::RECHAR* szStart = 0;
      const CAtlREMatchContext<>::RECHAR* szEnd = 0;
      mcUrl.GetMatch(nGroupIndex, &szStart, &szEnd);

      ptrdiff_t nLength = szEnd - szStart;
      printf("%d: /"%.*s/"/n", nGroupIndex, nLength, szStart);
   }

}      

出力:
0: "http"
1: "search.microsoft.com"
2: "/us/Search.asp"
3: "qu=atl&boolean=ALL"
4: "results"

Matchの結果は2番目のパラメータpContextが指すCAtlREMatchContextクラスによって返され、Matchの結果とその関連情報はすべてCAtlREMatchContextクラスに格納され、CAtlREMatchContextのメソッドとメンバーにアクセスすれば一致する結果が得られる.CAtlREMatchContext通過m_uNumGroupメンバーおよびGetMatch()メソッドは、呼び出し元に一致する結果情報を提供します.m_uNumGroupsはマッチング上のGroupのグループ数を表し、GetMatch()はそれに渡されたGroupのIndex値に基づいてマッチング上の文字列のpStartとpEndポインタを返し、呼び出し者はこの2つのポインタを持っているので、マッチング結果を容易に得ることができる.詳細については、CAtlRegExp Class GRETA GRETAは、マイクロソフト研究院が発表した正規表現テンプレートクラスライブラリです.GRETAには、C++オブジェクトと関数が含まれており、文字列のパターンマッチングと置換が容易になります.
  • 「rpattern:検索のパターン
  • 「match_results/subst_results:一致、置換結果を格納するコンテナ
  • 検索と置換の操作を実行するために、ユーザはまずマッチングルールを記述する文字列でrpatternオブジェクトを明示的に初期化し、次にマッチングする文字列をパラメータとしてmatch()やsubstitute()などのrpatternの関数を呼び出すと、マッチング後の結果を得ることができる.match()/substitute()呼び出しに失敗した場合、関数はfalseを返し、呼び出しに成功した場合、関数はtrueを返し、match_resultsオブジェクトはマッチング結果を格納します.例コードを見てください.
    #include <iostream>
    #include <string>
    #include "regexpr2.h"
    using namespace std;
    using namespace regex;
    int main() {
        match_results results;
        string str( "The book cost $12.34" );
        rpattern pat( "//$(//d+)(//.(//d//d))?" );  
        // Match a dollar sign followed by one or more digits,
        // optionally followed by a period and two more digits.
        // The double-escapes are necessary to satisfy the compiler.
        match_results::backref_type br = pat.match( str, results );
        if( br.matched ) {
            cout << "match success!" << endl;
            cout << "price: " << br << endl;
        } else {
            cout << "match failed!" << endl;
        }
        return 0;
    }      

    プログラム出力は次のようになります.
    match success!
    price: $12.34

    GRETAドキュメントを読むと、rpatternオブジェクトの詳細がわかり、検索ポリシーをカスタマイズしてより効率的になる方法を把握できます.注意:すべてのヘッダファイルregexpr 2.hの宣言はすべて名前空間regexの中にあり、ユーザーがその中のオブジェクトと関数を使用する場合、接頭辞「regex:::」、または予め「using namespace regex;なお、以下のサンプルコードでは、簡略化のため、「regex:::」接頭辞は省略する.著者らはgretaを生成した.libとregexpr 2.hファイルは、この2つのファイルのサポートだけでgretaを使用して正規表現を解析できます.マッチング速度が小さい異なる正規表現マッチングエンジンは、異なるマッチングモードが得意です.基準として、パターン:"^([0-9]+)(/-|$)(.*)$"マッチング文字列"100-this is a line of ftp response which contains a message string"を使用すると、GRETAのマッチング速度はboost(http://www.boost.org)正規表現ライブラリは約7倍速く、ATL 7のCATLRegExpより10倍速い!Boost Regexの説明ドキュメントには、多くのパターンのマッチングテストPerformance結果があります.この結果を比較すると、GRETAはほとんどの場合Boost Regexと性能が悪いが、Visual Studioを使っていることが分かった.Net 2003コンパイルの場合、GRETAはやや勝っている.Boost.Regex Boostはboost::basic_を提供していますregexは正規表現をサポートします.boost::basic_regexのデザインはstd::basic_によく似ていますstring:
    namespace boost{
    template <class charT, 
    	class traits = regex_traits<charT>, 
    	class Allocator = std::allocator<charT> > class basic_regex;
    typedef basic_regex<char> regex;
    typedef basic_regex<wchar_t> wregex;
    }      

    Boost Regexライブラリに付属するドキュメントは非常に豊富で、例はさらにすばらしく、例えば2つの例のプログラムがあり、多くないコードがあれば、プログラムは直接C++ファイルに対して文法のハイライトマークを行い、対応するHTML(converts a C++file to syntax highlighted HTML)を生成することができます.次の例では、文字列を一連のタグシンボル(split a string into tokens)に分割することができる.
    #include <list>
    #include <boost/regex.hpp>
    unsigned tokenise(std::list<std::string>& l, std::string& s)
    {
       return boost::regex_split(std::back_inserter(l), s);
    }
    
    #include <iostream>
    using namespace std;
    #if defined(BOOST_MSVC) || (defined(__BORLANDC__) && (__BORLANDC__ == 0x550))
    // problem with std::getline under MSVC6sp3
    istream& getline(istream& is, std::string& s)
    {
       s.erase();
       char c = is.get();
       while(c != ''''/n'''')
       {
          s.append(1, c);
          c = is.get();
       }
       return is;
    }
    #endif
    int main(int argc)
    {
       string s;
       list<string> l;
       do{
          if(argc == 1)
          {
             cout << "Enter text to split (or /"quit/" to exit): ";
             getline(cin, s);
             if(s == "quit") break;
          }
          else
             s = "This is a string of tokens";
          unsigned result = tokenise(l, s);
          cout << result << " tokens found" << endl;
          cout << "The remaining text is: /"" << s << "/"" << endl;
          while(l.size())
          {
             s = *(l.begin());
             l.pop_front();
             cout << s << endl;
          }
       }while(argc == 1);
       return 0;
    }