結果だけでなく過程も見てください

たい焼きさんの日々の奮闘を綴る日記です。

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

プライバシーポリシー お問い合わせ