C++標準のregex_search(正規表現)の動作と使用方法
Visual Studio 2010あたり(C++11の機能)からC++標準で正規表現が使えるようになってます。
(以前はboostを使う必要がありました)
regex_searchを使って、文字列全体から複数回マッチさせるにはどうしたらいいのか?
ネットを巡回していて、なぜか以下のことをガツンと言ってくれている人が
いなかったので備忘録として残しておきます。
まず、
regex_searchは最初に見つかった要素しか検出できない
ということです。
以下に例を挙げます。ターゲットとなる文字列はstrTargetです。
string strTarget = "aaa subghi123 subu56 cccsubhi88 subddd99"; regex pattern( "sub" ); smatch match_results; if ( regex_search(strTarget, match_results, pattern) ) { // マッチ }
マッチした要素を複数持てる、等の書き方を見たので混乱してしまったのですが、
上記の例では1つ目の「sub」しかヒットしません。
複数持てるとは、パターンを()で複数グルーピングしていた場合に、
1つ目にヒットした要素に関する結果を複数持てるということです。
ですので上の例で、パターンを「sub([a-z]+)([0-9]+)」とすると、
match_resultsには3つの要素が入ることになります。
まず1つ目はマッチした全体(subghi123)が、2つ目はghi、3つ目は123です。
全体を複数回マッチさせたい場合は、位置をずらして複数回regex_searchするしかありません。
マッチした結果(smatch型)のmatch_resultsには
マッチした文字列の先頭位置(positionメンバ関数で取得可能)、と長さ(lengthメンバ関数で取得可能)が
格納されていますので、毎回この分を加算しながら文字列全体をregex_searchすれば良いです。
string strTarget = "aaa subghi123 subu56 cccsubhi88 subddd99"; regex pattern( "sub([a-z]+)([0-9]+)" ); smatch match_results; vector<string> vMatchedStrings; for ( auto it = strTarget.begin(); regex_search( it, strTarget.end(), match_results, pattern ); it += match_results.position(0) + match_results.length(0) ) { vMatchedStrings.push_back( match_results.str(0) ); }
マッチした結果は、vMatchedStringsに格納されます。
vMatchedStringsの内容は以下のようになります。
subghi123 subu56 subhi88 subddd99
※ちなみにautoキーワードは型を自動判別してくれるキーワードでこれもC++11(Visual Studioでは2010)
からの新機能のようです。この場合string::iteratorを自動判別してくれるようです。
C言語に昔からあるauto変数のことではないの注意が必要ですよ。
参考サイト
(C++)正規表現で、1行の文字列内でパターンマッチする全ての文字列を出力したい
http://dixq.net/forum/viewtopic.php?t=14196&p=113104