移動先 先頭, , , 末尾 セクション, 目次.

Posix Entry Points

このセクションはSandra Loosemore, Richard M. Stallman, Roland McGrath, Andrew Oramによる The GNU C Libraryリファレンスマニュアルから抜 粋したものである。

GNU CライブラリはPOSIX.2の標準インターフェースをサポートしている。 このインターフェースを使用するプログラムは`rxposix.h'という ヘッダーファイルをインクルードするのが良い。

POSIX Regular Expression Compilation

正規表現とのマッチングを実際に行うには、その正規表現をコンパイル しなければならない。これは本当のコンパイルではなく、コンピューターの命 令コードの代わりに特殊なデータ構造を生成する。しかし、これは通常のコン パイルと同じようにパターンの"実行"が早くできるようにするためのもので ある(コンパイルした正規表現を使ってマッチングする方法については セクション Matching a Compiled POSIX Regular Expressionを参照)。

There is a special data type for compiled regular expressions: コンパイル済みの正規表現のための特殊なデータ型がある。

Data Type: regex_t
このオブジェクト型はコンパイル済みの正規表現を保持する。 これは実際には構造体であり、プログラムから参照すべきフィールドが ただ一つだけある:

re_nsub
このフィールドはコンパイルされた正規表現中にあった parenthetical subexpression (括弧で括られた部分正規表現) の数を保持している。

他にも幾つかのフィールドがあるが、ここでは説明しない。 それは、ライブラリ中の関数だけがそういったフィールドを使用すべき だからである。

regex_tオブジェクトを作成したら、regcompを 呼び出して正規表現をコンパイルすることができる。

Function: int regcomp (regex_t *compiled, const char *pattern, int cflags)
Function: int regncomp (regex_t *compiled, const char *pattern, int len, int cflags)
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を呼び出すときには matchptrnmatchに0をセットして呼び出す。

REG_NOSUBを使わなかったのならば、コンパイルされた正規表現はいく つの部分正規表現がマッチしたかを記録する能力を持っている。また、 regcompは(コンパイルした正規表現中に)部分正規表現がいくつあった かをcompiled->re_nsubに格納する。この値を使って、部分正規 表現のマッチに関する情報を格納するための配列をどのくらいの大きさで確保 すれば良いのかを決定することができる。

正規表現のコンパイルに成功した場合にはregcomp0を返し、 成功しなかった場合にはゼロ以外のエラーコードを返す(後述の一覧を参照)。 regerrorを使って、非ゼロの戻り値の原因を表すエラーメッセージ文字 列を生成することができる。セクション POSIX Regexp Matching Cleanupを参照. を参照のこと。

以下に挙げるのはregcompが返す可能性のある非ゼロの値である。

REG_BADBR
正規表現中に不正な書式の`\{...\}'があった。正しい`\{...\}' には、ただ一つの数か、もしくはカンマで区切られていて、かつ昇順に並んで いる二つの数がなければならない。
REG_BADPAT
正規表現中に構文エラー(syntax error)があった。
REG_BADRPT
`?'`*'のような繰り返し演算子(repetition operator)が不正な位 置にあった(繰り返しの対象となる部分正規表現が演算子の前になかった)。
REG_ECOLLATE
正規表現が不正な照合要素(collating element)を参照していた(カレントのロ カールで定義されていない文字列の照合)。
REG_ECTYPE
正規表現が不正なキャラクタクラス名を参照していた。
REG_EESCAPE
正規表現が`\'で終わっていた。
REG_ESUBREG
`\digit'という表現で不正な数値が使用された。
REG_EBRACK
正規表現中に対応の取れていない角カッコ(square brackets)があった。
REG_EPAREN
拡張正規表現(extended regular expression)で対応の取れていないカッコがあ ったか、基本正規表現(basic reglular expression)で対応の取れていない`\('`\)'があった。
REG_EBRACE
正規表現中に対応の取れていない`\{'`\}'があった。
REG_ERANGE
範囲式(range expression)の終端の一つが不正なものであった。
REG_ESPACE
regcompがメモリーを使いきってしまった。

Flags for POSIX Regular Expressions

regcompを使って正規表現を翻訳するときにcflagsで指定するこ とのできるビットフラグがある。

REG_EXTENDED
パターンを基本正規表現(basic regular expression)ではなく、 拡張正規表現(extended regular expression)として扱う。
REG_ICASE
文字の比較の際に大小文字の区別を無視する。
REG_NOSUB
配列matches-ptr の内容を格納することを考慮しない。
REG_NEWLINE
stringにある改行を、stringを複数行に分割するものとして扱う。 これにより`$'は改行の直前にマッチし、`^'は改行の直後にマッチ するようになる。同様に`.'は改行とマッチしなくなり、`[^...]' も改行とはマッチしない。 これが指定されていなければ、改行は他の通常キャラクタと同じように振る舞 う。

Matching a Compiled POSIX Regular Expression

正規表現をコンパイルすれば、セクション POSIX Regular Expression Compilationを参照にあるように regexecを使って文字列に対してマッチを行うことができる。文字列中 のどこかでマッチしたら、正規表現中にアンカーキャラクター(anchor character, `^'または`$')が含まれていない限り、マッチに成功したとみなされ る。

Function: int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int eflags)
Function: int regnexec (regex_t *compiled, char *string, int len, size_t nmatch, regmatch_t matchptr [], int eflags)
この関数は*compiledにあるコンパイル済み 正規表現のstringに対するマッチを試みる。

regexecは正規表現がマッチすれば0を返し、マッチしなければ ゼロ以外の値を返す。非ゼロの値の意味するところは後述の一覧を参照のこと。 regerrorを使って、非ゼロの戻り値の原因を表すエラーメッセージ文字 列を生成することができる。セクション POSIX Regexp Matching Cleanupを参照. を参照のこと。

パラメータ string は検索対象となるテキストを指す。regexec を使用するとき、stringは 0で終端されていなければならない。 regnexecを使う場合には、stringはその長さがlenでなけ ればならない。

regnexecは標準関数ではない。POSIXに厳密に従うプログラムはこれを 使うべきではない。

eflagsという引数は、幾つかのオプションを使用可能にする ビットフラグがまとまったワードである。

string中で正規表現やその部分正規表現(subexpression)が実際にどの部 分にマッチしたかという情報は、var{matchptr} と nmatchという引数を 使うことによって得ることができる。マッチした部分がなかった場合にはnmatch0が、matchptrにはNULLがセットされている。セクション Match Results with Subexpressionsを参照.

正規表現のマッチはその正規表現をコンパイルしたときと同じロカール(locales) のもとで行わなければならない。

関数regexec は引数eflags 中に置かれた以下のフラグを受け付 ける:

REG_NOTBOL
指定文字列の先頭を行の先頭とみなさない。より一般的には、 指定文字列の前に何かがあるかもしれないという仮定をしない。
REG_NOTEOL
指定文字列の終端を行の終端としてみなさない。より一般的には、 指定文字列の後に何かが続いているかもしれないという仮定をしない。

以下はregexecが返す可能性がある非0の戻り値の一覧である。

REG_NOMATCH
パターンが文字列にマッチしなかった。これは実際にはエラーではない。
REG_ESPACE
regexecがメモリーを使いきってしまった。

Match Results with Subexpressions

regexecpatternのかっこ付き部分式(parenthetical subexpression) にマッチしたとき、それがマッチしたstringの部分を記録する。この関 数は構造体 regmatch_tの配列中の要素にその情報を格納して返す。こ の配列の第一要素(添え字 0)は正規表現全体にマッチした部分文字列を 記録する。その他の配列要素は、かっこ付き部分式にマッチした部分の先頭と 末尾とを記録する。

Data Type: regmatch_t
これはregexecに渡したmatcharrayという配列のデータ型である。 この型は以下に挙げる二つのフィールドから構成される。

rm_so
部分文字列の始まっているstring中のオフセット。 この値をstringのアドレスに加えれば 部分文字列のアドレスを取得できる。
rm_eo
部分文字列の終端位置を表すstring中でのオフセット。

Data Type: regoff_t
regoff_tは別の符号つき整数型に対する別名(alias)である。 regmatch_tのフィールドはregoff_tの型を 持っている。

regmatch_t の要素 は部分正規表現の場所と一致する。最初の要素(添 え字が1)は最初にマッチした部分正規表現を記録し、二番目の要素は二番目の 部分正規表現にマッチし…となる。部分正規表現の順序はそれらが始まる順序 である。

regexecを呼び出すときには、配列matchptrがどのくらいの長さ (要素数が幾つか)ということをnmatchという引数を使って指定する。こ れはregexecにどのくらい格納べき要素があるかということを示すもの である。実際の正規表現がnmatchよりも多い数の部分正規表現を持って いた場合、その数を越えた分のオフセット情報はセットされない。しかし、こ れはパターンが特定の文字列にマッチするかしないかを変えてしまうようなも のではない。

regexecがマッチした部分式の場所に関する情報を返さないようにした い場合、nmatchに0をセットするか、REG_NOSUBフラグを使って、 regcompでパターンをコンパイルすればよい。

Complications in Subexpression Matching

部分正規表現はキャラクタを持たない部分文字列にマッチすることがある。こ れは`f\(o*\)'`fum'という文字列とマッチしたようなときに発生 する(これは実際には単なる`f'にマッチしている)。このような場合、オ フセットの値は検索対象の文字列中にある空の部分文字列を指す。この例の場 合では、オフセットは両方とも1になる。

ときには正規表現全体が部分正規表現全てを使わなくてもマッチできることが ある。たとえば、`ba\(na\)*'`ba'という文字列にマッチしたとき には(カッコで囲まれた)部分正規表現は使われていない。この状態になったと き、regexecはその部分正規表現に対応する要素のフィールド両方に -1を格納する。

正規表現全体が、部分正規表現を二度以上繰り返してマッチすることがある。 たとえば、`ba\(na\)*'`bananana'という文字列にマッチしたとき、 (カッコで囲まれた)部分正規表現は三回繰り返されている。この状態になった とき、regexは通常、部分正規表現にマッチした文字列の最後の部分の オフセットを格納する。`bananana'の場合、このオフセットは68である。

しかし、最後にマッチしたものが常に選択されたものであるわけではない。よ り正確に言うと、最後にマッチする可能性のあるものは、優先されるも のであるということである。これはつまり、ある部分式が別の部分式の中に現 れた場合には、その結果は内側の部分式が外側の部分式に最後にマッチしたも のを反映するような結果となるということである。例として `\(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" が使われていないと報告するのである。

POSIX Regexp Matching Cleanup

コンパイル済み正規表現を使い終わったら、regfreeを呼び出して (コンパイルのために確保した)メモリー領域を解放することができる。

Function: void regfree (regex_t *compiled)
regfreeを呼び出すことによって、*compiledが指してい る領域を解放する。このドキュメントでは説明されていないようなregex_t の内部フィールドも含まれる。

regfree*compiledというオブジェクトそれ自身の 解放はしない。

ある正規表現のためにregex_t構造体を使ったなら、その構造体を他の 正規表現に使いまわしする前に常にregfreeを呼び出して領域を解放し たほうが良い。

regcompregexecがエラーを報告した場合、 regerrorを使ってそのエラーを対応するメッセージ文字列に 変換することができる。

Function: size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)
この関数は、errcodeに対応するエラーメッセージの文字列を生成し、そ れをbufferから始まるlengthバイトの領域に格納する。引数 compiledには。エラーが発生したときにrecompregexec に渡していたのと同じコンパイル済み正規表現を渡す。あるいは、compiledNULLを設定することもできる。これでも意味あるエラーメッセージを 取得することができるが、詳細はわからないかもしれない。

エラーメッセージが(終端のナルキャラクターも含めて)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;
}

移動先 先頭, , , 末尾 セクション, 目次.