このセクションはSandra Loosemore, Richard M. Stallman, Roland McGrath, Andrew Oramによる The GNU C Libraryリファレンスマニュアルから抜 粋したものである。
GNU CライブラリはPOSIX.2の標準インターフェースをサポートしている。 このインターフェースを使用するプログラムは`rxposix.h'という ヘッダーファイルをインクルードするのが良い。
正規表現とのマッチングを実際に行うには、その正規表現をコンパイル しなければならない。これは本当のコンパイルではなく、コンピューターの命 令コードの代わりに特殊なデータ構造を生成する。しかし、これは通常のコン パイルと同じようにパターンの"実行"が早くできるようにするためのもので ある(コンパイルした正規表現を使ってマッチングする方法については セクション Matching a Compiled POSIX Regular Expressionを参照)。
There is a special data type for compiled regular expressions: コンパイル済みの正規表現のための特殊なデータ型がある。
re_nsub
他にも幾つかのフィールドがあるが、ここでは説明しない。 それは、ライブラリ中の関数だけがそういったフィールドを使用すべき だからである。
regex_t
オブジェクトを作成したら、regcomp
を
呼び出して正規表現をコンパイルすることができる。
regcomp
という関数は、正規表現をregexec
に渡して文字列との
マッチングをさせることのできるデータ構造に"コンパイル"する。コンパイ
ルされた正規表現の形式は、効果的なマッチングのために設計されている。
regcomp
はコンパイルの結果を*var{compiled
}に格納する。
パラメータpatternはコンパイル対象の正規表現を指している。regcomp
を使うとき、patternは0で終端されていなければならない。regncomp
を使うときには、patternは長さが len でなければならない。
regncomp
は標準関数ではない。厳密なPOSIXプログラムはこの関数を使
うべきではない。
この関数(regcomp
)は、使用者がregex_t
型のオブジェクトの割
り付けを行い、そのアドレスが渡されることを期待している。
regex_t
型のオブジェクトを解放する前に、それをregfree
に
渡さなければならない。以後のRX関数の呼び出しがきちんと動作するよ
うに、これに従うこと。
cflagsという引数は正規表現の構文(syntax)や意味づけ(semantics)を制 御するための様々なオプションを指定するためのものである。セクション Flags for POSIX Regular Expressionsを参照.
REG_NOSUB
というフラグを使った場合、regcomp
はコンパイル済
み正規表現の内で、いくつの部分正規表現がマッチしたかを記録するために必
要な情報を省略してしまう。この場合、regexec
を呼び出すときには
matchptrとnmatchに0をセットして呼び出す。
REG_NOSUB
を使わなかったのならば、コンパイルされた正規表現はいく
つの部分正規表現がマッチしたかを記録する能力を持っている。また、
regcomp
は(コンパイルした正規表現中に)部分正規表現がいくつあった
かをcompiled->re_nsub
に格納する。この値を使って、部分正規
表現のマッチに関する情報を格納するための配列をどのくらいの大きさで確保
すれば良いのかを決定することができる。
正規表現のコンパイルに成功した場合にはregcomp
は0
を返し、
成功しなかった場合にはゼロ以外のエラーコードを返す(後述の一覧を参照)。
regerror
を使って、非ゼロの戻り値の原因を表すエラーメッセージ文字
列を生成することができる。セクション POSIX Regexp Matching Cleanupを参照. を参照のこと。
以下に挙げるのはregcomp
が返す可能性のある非ゼロの値である。
REG_BADBR
REG_BADPAT
REG_BADRPT
REG_ECOLLATE
REG_ECTYPE
REG_EESCAPE
REG_ESUBREG
REG_EBRACK
REG_EPAREN
REG_EBRACE
REG_ERANGE
REG_ESPACE
regcomp
がメモリーを使いきってしまった。
regcomp
を使って正規表現を翻訳するときにcflagsで指定するこ
とのできるビットフラグがある。
REG_EXTENDED
REG_ICASE
REG_NOSUB
REG_NEWLINE
正規表現をコンパイルすれば、セクション POSIX Regular Expression Compilationを参照にあるように
regexec
を使って文字列に対してマッチを行うことができる。文字列中
のどこかでマッチしたら、正規表現中にアンカーキャラクター(anchor character,
`^'または`$')が含まれていない限り、マッチに成功したとみなされ
る。
*compiled
にあるコンパイル済み
正規表現のstringに対するマッチを試みる。
regexec
は正規表現がマッチすれば0
を返し、マッチしなければ
ゼロ以外の値を返す。非ゼロの値の意味するところは後述の一覧を参照のこと。
regerror
を使って、非ゼロの戻り値の原因を表すエラーメッセージ文字
列を生成することができる。セクション POSIX Regexp Matching Cleanupを参照. を参照のこと。
パラメータ string は検索対象となるテキストを指す。regexec
を使用するとき、stringは 0で終端されていなければならない。
regnexec
を使う場合には、stringはその長さがlenでなけ
ればならない。
regnexec
は標準関数ではない。POSIXに厳密に従うプログラムはこれを
使うべきではない。
eflagsという引数は、幾つかのオプションを使用可能にする ビットフラグがまとまったワードである。
string中で正規表現やその部分正規表現(subexpression)が実際にどの部
分にマッチしたかという情報は、var{matchptr} と nmatchという引数を
使うことによって得ることができる。マッチした部分がなかった場合にはnmatchに
0
が、matchptrにはNULL
がセットされている。セクション Match Results with Subexpressionsを参照.
正規表現のマッチはその正規表現をコンパイルしたときと同じロカール(locales) のもとで行わなければならない。
関数regexec
は引数eflags 中に置かれた以下のフラグを受け付
ける:
REG_NOTBOL
REG_NOTEOL
以下はregexec
が返す可能性がある非0の戻り値の一覧である。
REG_NOMATCH
REG_ESPACE
regexec
がメモリーを使いきってしまった。
regexec
はpatternのかっこ付き部分式(parenthetical subexpression)
にマッチしたとき、それがマッチしたstringの部分を記録する。この関
数は構造体 regmatch_t
の配列中の要素にその情報を格納して返す。こ
の配列の第一要素(添え字 0
)は正規表現全体にマッチした部分文字列を
記録する。その他の配列要素は、かっこ付き部分式にマッチした部分の先頭と
末尾とを記録する。
regexec
に渡したmatcharrayという配列のデータ型である。
この型は以下に挙げる二つのフィールドから構成される。
rm_so
rm_eo
regoff_t
は別の符号つき整数型に対する別名(alias)である。
regmatch_t
のフィールドはregoff_t
の型を
持っている。
regmatch_t
の要素 は部分正規表現の場所と一致する。最初の要素(添
え字が1)は最初にマッチした部分正規表現を記録し、二番目の要素は二番目の
部分正規表現にマッチし…となる。部分正規表現の順序はそれらが始まる順序
である。
regexec
を呼び出すときには、配列matchptrがどのくらいの長さ
(要素数が幾つか)ということをnmatchという引数を使って指定する。こ
れはregexec
にどのくらい格納べき要素があるかということを示すもの
である。実際の正規表現がnmatchよりも多い数の部分正規表現を持って
いた場合、その数を越えた分のオフセット情報はセットされない。しかし、こ
れはパターンが特定の文字列にマッチするかしないかを変えてしまうようなも
のではない。
regexec
がマッチした部分式の場所に関する情報を返さないようにした
い場合、nmatchに0をセットするか、REG_NOSUB
フラグを使って、
regcomp
でパターンをコンパイルすればよい。
部分正規表現はキャラクタを持たない部分文字列にマッチすることがある。こ
れは`f\(o*\)'が`fum'という文字列とマッチしたようなときに発生
する(これは実際には単なる`f'にマッチしている)。このような場合、オ
フセットの値は検索対象の文字列中にある空の部分文字列を指す。この例の場
合では、オフセットは両方とも1
になる。
ときには正規表現全体が部分正規表現全てを使わなくてもマッチできることが
ある。たとえば、`ba\(na\)*'が`ba'という文字列にマッチしたとき
には(カッコで囲まれた)部分正規表現は使われていない。この状態になったと
き、regexec
はその部分正規表現に対応する要素のフィールド両方に
-1
を格納する。
正規表現全体が、部分正規表現を二度以上繰り返してマッチすることがある。
たとえば、`ba\(na\)*'が`bananana'という文字列にマッチしたとき、
(カッコで囲まれた)部分正規表現は三回繰り返されている。この状態になった
とき、regex
は通常、部分正規表現にマッチした文字列の最後の部分の
オフセットを格納する。`bananana'の場合、このオフセットは6
と
8
である。
しかし、最後にマッチしたものが常に選択されたものであるわけではない。よ
り正確に言うと、最後にマッチする可能性のあるものは、優先されるも
のであるということである。これはつまり、ある部分式が別の部分式の中に現
れた場合には、その結果は内側の部分式が外側の部分式に最後にマッチしたも
のを反映するような結果となるということである。例として `\(ba\(na\)*s \)*'
と 文字列`bananas bas 'をマッチングしたときを考えてみよう。内側の
式に最後に実際にマッチしたものは最初の単語の終端付近である。しかし、こ
れは二番目の単語についてもあてはまるのである。そしてここでマッチ
は失敗する。regexec
は部分式 "na" は使われていないと報告する。
match in the second word because the other alternative is used there.
もう一つこの規則が適用されるのは、正規表現 `\(ba\(na\)*s \|nefer\(ti\)* \)*'が
`bananas nefertiti'にマッチするときである。部分式 "na" は最初の
単語にマッチするが、二番目の単語にはマッチしない。なぜなら別の選択肢が
そこで使われるからである。もう一度繰り返そう。外側の部分式の二番目の繰
り返しは最初のものをオーバーライドし、そして二番目の繰り返しの中にある
部分式 "na" は使用されないのである。このために、regexec
は部分
式 "na" が使われていないと報告するのである。
コンパイル済み正規表現を使い終わったら、regfree
を呼び出して
(コンパイルのために確保した)メモリー領域を解放することができる。
regfree
を呼び出すことによって、*compiled
が指してい
る領域を解放する。このドキュメントでは説明されていないようなregex_t
の内部フィールドも含まれる。
regfree
は*compiled
というオブジェクトそれ自身の
解放はしない。
ある正規表現のためにregex_t
構造体を使ったなら、その構造体を他の
正規表現に使いまわしする前に常にregfree
を呼び出して領域を解放し
たほうが良い。
regcomp
やregexec
がエラーを報告した場合、
regerror
を使ってそのエラーを対応するメッセージ文字列に
変換することができる。
recomp
やregexec
に渡していたのと同じコンパイル済み正規表現を渡す。あるいは、compiled
にNULL
を設定することもできる。これでも意味あるエラーメッセージを
取得することができるが、詳細はわからないかもしれない。
エラーメッセージが(終端のナルキャラクターも含めて)lengthバイトに
収まらなければ、regerror
はメッセージを切りつめる。regerror
が格納する文字列は、たとえメッセージの切りつめが行われても常にナルで終
端される。
regerror
の戻り値は、エラーメッセージ全体を納めるのに最低限必要な
長さである。もしこれがlenght未満であれば、エラーメッセージは切り
詰められることはなく使うことが可能である。lengthの方が小さい場合
にはバッファーをより大きくして再度regerror
を呼び出した方が良いだ
ろう。
以下例示するのはエラーメッセージのためのバッファを常に動的に割り当てて
regerror
を使う関数である。
char *get_regerror (int errcode, regex_t *compiled) { size_t length = regerror (errcode, compiled, NULL, 0); char *buffer = xmalloc (length); (void) regerror (errcode, compiled, buffer, length); return buffer; }