よくある質問と回答
Boost.Regex でエスケープ文字がうまく動作しないが、何がまずいのか
C++ のコードに正規表現を埋め込む場合は、エスケープ文字が 2 度処理されることを忘れてはならない。1 度目は C++ コンパイラで 2 度目は Boost.Regex の正規表現コンパイラである。よって正規表現 \d+
を Boost.Regex に渡すときは "\d+" をコードに埋め込む必要がある。同様に直値のバックスラッシュをマッチさせるには、コードには "\\\\"
を埋め込む必要がある。
どうやっても regex_match
が常に偽を返すのだが、何がまずいのか
アルゴリズム regex_match
は、正規表現のマッチがテキスト全体に対して成功する場合のみ成功する。テキスト内の、正規表現にマッチする部分文字列を検索する場合は regex_search
を使用する。
POSIX 正規表現で括弧を使うとマッチ結果が変わるのはなぜか
Perl と異なり、POSIX(拡張および基本)正規表現では、括弧はマーク付けを行うだけでなく最良マッチの決定も行う。正規表現を POSIX 基本、あるいは POSIX 拡張正規表現としてコンパイルすると、Boost.Regex は POSIX 標準の最左最長規則にしたがってマッチを決定する。よって正規表現全体を評価した上で可能性のあるマッチが 2 つ以上ある場合、次の 1 番目の部分式を、その次は 2 番目の部分式、となる。そのため、00123
に対して (0*)([0-9]*)
でマッチをかけると $1 = "00" 、$2 = "123" が生成されるが、00123
に対して 0*([0-9]*)
でマッチをかけると $1 = "00123" が生成される。
$1 を 123
の部分のみにマッチさせたい場合は、0*([1-9][0-9]*)
といった正規表現を使用するとよい。
文字範囲が正しく動作しないのはなぜか(POSIX モードのみ)
POSIX 標準は文字範囲式がロカールを考慮すると規定している。よって、例えば正規表現 [A-Z]
は照合順が ‘A’ から ‘Z’ の間となるあらゆる照合要素にマッチする。これが意味するところは “C” と “POSIX” 以外の大部分のロカールでは、[A-Z]
が例えば ‟t” 1 文字にマッチするという、大部分の人が期待しない(あるいは少なくとも大部分の人が正規表現エンジンの動作として考えていない)動作をするということである。このような理由から、Boost.Regex の既定の動作(Perl モード)ではコンパイルフラグ regex_constants::collate
を設定しない限りロカール依存の照合は無効になっている。しかしながら、regex_constants::extended
や regex_constants::basic
といった既定以外のコンパイルフラグを設定するとロカール依存の照合が有効になる。これは内部的に regex_constants::extended
や regex_constants::basic
を使用する POSIX API 関数にも適用される。 1
関数に例外仕様がないのはなぜか。ライブラリが投げる例外にはどのようなものがあるか
すべてのコンパイラが例外仕様をサポート(あるいは尊重)しているわけではなく、サポートしているコンパイラの中にも効率が低下するものがある。コンパイラの処理が現在よりも改善される日が来れば、例外仕様を追加するかもしれない。本ライブラリが投げる例外は 3 種類のみである。boost::regex_error
は basic_regex
が正規表現のコンパイル中に投げる可能性がある。std::runtime_error
は、basic_regex::imbue
が存在しないメッセージカタログを開こうとしたとき、regex_search
および regex_match
の検索時間が「限界を超えた」とき、あるいは RegEx::GrepFiles
および RegEx::FindFiles
が開けないファイルを開こうとしたときに投げる。最後に std::bad_alloc
は本ライブラリのあらゆる関数が投げる可能性がある。
regex_match
、regex_search
、regex_grep
、regex_format
、regex_merge
の「便利」版が使用できないのはなぜか
これらの版が利用可能かどうかはコンパイラの能力に依存する。これらの関数の形式を決定する規則はかなり複雑であり、ヘルプに掲載しているのは標準準拠コンパイラでの形式のみである。あなたのコンパイラがどの形式をサポートしているか調べるには、<boost/regex.hpp>
を C++ プリプロセッサにかけ、出力ファイルから目的の関数を探すとよい。しかしながら、ごく少数のコンパイラがこれらの関数の多重定義を正しく解釈できないことに注意していただきたい。
- 1
regex_constants::nocollate
が有効な場合は、ライブラリの動作は他の設定に関わらずLC_COLLATE
ロカールカテゴリが “C” であるのと同様になる。