最終更新日時:
が更新

履歴 編集

Regex++, FAQ.

Copyright (c) 1998-2001

Dr John Maddock

Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Dr John Maddock makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.


Q. 正規表現の中で丸括弧を使うと、なぜ一致の結果が変わるのですか?

丸括弧は印付けをするだけではない。 同様に、何が最も一致するかを決定する。 regex++ の特性は、何が一致するかを決定するのに 最左・最長という POSIX 標準に従っている。 だからもし全ての表現を検討した上で、ひとつ以上の可能な一致があれば、最初の子表現、第2の子表現、第3の・・・と優先されて一致する。 つまり、

"(0*)([0-9]*)" against "00123" は次のものを作る:

$1 = "00"
$2 = "123"

一方、

"0*([0-9)*" against "00123" は次のものを作る:

$1 = "00123"

$1が "123" とだけ一致するとしたら、それは最左最長の一致である "00123" との一致よりも望ましくない。 もし $1 を "123" とのみ一致させたければ、次のようなものを使う必要がある。 つまり:

"0*([1-9][0-9]*)"

という表現である。

Q. コンフィギュアは、私のコンパイラがテンプレートの実体を結合出来ないと言ってきます。これはどういう意味ですか?

A. あなたがテンプレートコードをコンパイルするとき、最終的には複数の翻訳単位で同じテンプレートの実体が出来る。 このため、もしあなたのコンパイラ/リンカが、これらのテンプレートの実体を実行ファイルの中のひとつのレコードに結合するのに十分賢くなければ、リンク時のエラーが起きる。 コンフィギュアを実行した後にこの警告が出ても、次のような場合には libregex++.a とリンクすることが可能である。

  1. 低水準テンプレートクラス(reg_expression<>, match_results<>, etc.) のみを単一の翻訳単位から使っていて、regex++ の他の部分は使っていない場合。
  2. POSIX API 関数(regcomp, regexec, etc.)だけを使っていて、 regex++ の他の部分を使っていない場合。
  3. 高水準のクラス RegEx だけを使っていて、 regex++ の他の部分を使っていない場合。

もうひとつの選択肢は、最上位インクルードファイルを作成することである。 これには regex++ のソースファイル全て、あなたが regex++ を利用しているソースファイル全てをインクルードする。 そしてこの最上位インクルードファイルを単一の翻訳単位として、コンパイルしリンクする。

Q. コンフィギュアは私のコンパイラがアーカイブファイルからテンプレートの実体を結合できないと言ってきます。これはどういう意味ですか?

A. あなたがテンプレートコードをコンパイルするとき、最終的に複数の翻訳単位に同じテンプレートの実体が出来る。 これにより、もしあなたのコンパイラ/リンカが、これらのテンプレートの実体を実行ファイルの中のひとつのレコードに結合するのに十分賢くなければ、リンク時にエラーが起きる。 通常の .cpp ファイルと .o ファイルに対してはこれが可能だが、オブジェクトファイルがライブラリアーカイブに置かれていると、これに失敗するコンパイラもある。 コンフィギュアを実行した後にこの警告が出ても、次のような場合は libregex++.a とリンクすることが可能である。

  1. 低水準テンプレートクラス(reg_expression<>, match_results<>, etc.) のみを単一の翻訳単位から使っていて、regex++ の他の部分は使っていない場合。
  2. POSIX API 関数(regcomp, regexec, etc.)だけを使っていて、 regex++ の他の部分を使っていない場合。
  3. 高水準のクラス RegEx だけを使っていて、 regex++ の他の部分を使っていない場合。

もう一つの選択肢は、 libregex++.a をリンクする代わりに、 regex++ のソースファイルを直接あなたのプロジェクトに追加することである。 これは通常、 libregex++.a でリンク時エラーが起きる場合のみ、行うべきである。

Q. コンフィギュアは、私のコンパイラが switch 文を含むテンプレートを結合出来ないと言ってきます。これはどういう意味ですか?

A. 静的なデータを含むテンプレートを結合できないコンパイラもある。 これには、コードと同様に、しかし暗黙的に静的データを生成する switch 文も含む。 主にこれは、 egcs コンパイラに影響する (しかし gcc 2.81 も同じ問題を持っていることに注意せよ)。 コンパイラはコードをコンパイルし、リンクすることが出来る。 しかしコードと、コードが使う静的データは分離してしまうので、そのコードは実行できない。 regex++ のデフォルトの振る舞いは、 無名名前空間の中で "problem" テンプレートを宣言することにより、この問題を修復しようとするので、テンプレートは内部リンケージをもつ。 これが、大量のコード膨張を引き起こすことに注意せよ。 もしコンパイラが名前空間をサポートしていないか、コード膨張が問題になったら、単一翻訳単位の中に全てのテンプレートを置くための上のガイドラインに従うこと。 そして、 boost/regex/config.hpp を編集し、 BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE を定義しないようにすること。

Q. 私は regex++ でエスケープ文字を使うことが出来ません。何が起こっているのですか?

A. もし C++ コードの中に正規表現を埋め込んでいるなら、エスケープ文字が2度処理されることを忘れないこと: 一度は C++ コンパイラによって、もう一度は regex++ 正規表現コンパイラによってである。 正規表現 \d+ を regex++ に渡すには、 "\\d+" をコードに埋め込む必要がある。 同様にリテラルとしてバックスラッシュに一致するには、コードに "\\\\" を埋め込む必要があるだろう。

Q. なぜ文字範囲が適切に動作しないのですか?

A. POSIX 標準は、文字範囲表現がロケールに敏感であること明示している。 例えば正規表現 [A-Z] は 'A' と 'Z' の間に並ぶあらゆる照合要素に一致する。 これは、 "C" や "POSIX" 以外のほとんどのロケールで、例えば[A-Z] は単一文字 't' にマッチする。 これはあまり期待されていない動作である。 また、少なくとも正規表現エンジンによってこうなることは、多くの場合期待されていないだろう。 この理由で、 regex++ のデフォルトの振る舞いは、コンパイル時フラグ regbase::nocollate を設定することでロケールに敏感な照合を行わない (このフラグは regbase::normal により設定されている)。 しかしもし、デフォルトでないコンパイル時フラグを設定すれば (例えば regbase::extendedregbase::basic) ロケールに依存する照合が可能になる。 これはまた、内部的に regbase::extendedregbase::basic を使っている POSIX API 関数にも適用される。 後者の場合、もしロケールに敏感な照合を行いたくなければ、 REG_NOCOLLATEREG_BASICREG_EXTENDED を組み合わせて使えばよい。 [注意: regbase::nocollate が作用しているとき、ライブラリは、実際にの設定値に関わらず、_COLLATE ロケートカテゴリーが常に "C" である "かのように" 振る舞う。]

Q. なぜ私は、「簡易版の」 query_match/reg_search/reg_grep/reg_format/reg_merge を使うことが出来ないのですか?

A. これらの簡易版はあなたのコンパイラの能力によって使えたり使えなかったりする。 これらの関数の形式を決定する規則は極めて複雑である。 そして標準に準拠しているコンパイラで利用可能な版は、ヘルプの中に記載されている。 あなたのコンパイラが何をサポートしているかを見るには、あなたの C++ プリプロセッサで、 <boost/regex.hpp> を実行し、あなたが感心のある関数をその出力ファイルで探せばよい。

Q. なぜどの関数にも、例外仕様がないのですか?ライブラリはどんな例外を投げるのですか?

A. 全てのコンパイラが、例外仕様をサポートしたり、支持しているわけではない。 それをサポートしていても、あまり効果を持たせていないものもある。 例外仕様はコンパイラがこれをもう少しちゃんと扱い始めたら、その時に付け加えられるだろう。 ライブラリは 3 つの型の例外のみを投げる。 boost::bad_expression は 正規表現のコンパイル時に reg_expression によって投げられる。 std::runtime_errorreg_expression::imbue の呼び出しが、存在しないメッセージカタログを開こうとしたときか、 RegEx::GrepFilesRegEx::FindFiles が開くことの出来ないファイルを開こうとしたときに投げられる。 最後に、 std::bad_alloc はこのライブラリのおおよそどの関数でも投げられる。


Copyright Dr John Maddock 1998-2001 all rights reserved.


Japanese Translation Copyright (C) 2003 Kohske Takahashi

オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。 このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。 また、いかなる目的に対しても、その利用が適していることを関知しない。