RE_FORMAT(7)

名称
re_format - POSIX 1003.2 正規表現

解説
p1003.2 において定義されているように、 正規表現 (“RE”) には 2 つの形式があります。 ひとつは現代正規表現 (大雑把にいうと egrep(1) で使用されているもので、1003.2 での “拡張” 正規表現) で、もうひとつは旧式正規表現 (これも大雑把には ed(1) で使用されているもので、1003.2 での “基本” 正規表現) です。 旧式正規表現は大抵の場合いくつかの古くからあるプログラムでの 旧バージョンとの互換性のために存在しています。 これについては最後に説明します。 p1003.2 は正規表現の構文と意味のいくつかの部分を明確に定めないままに しています。 他の p1003.2 の実装とは完全な互換性がないかもしれない これらの部分については、`‡' によって印をつけて示します。

正規表現 (現代正規表現) はひとつ‡もしくはそれ以上の空でない‡ 枝 (branch) を ‘|’ によって区切ったものです。 いずれかの枝にマッチすると正規表現はマッチします。

枝はひとつ‡以上の ピース (piece) が結合されたものです。 枝は最初のピース、次のピース...とすべてがマッチしたものにマッチします。

ピースは アトム (atom) 、もしくはそれに単一の ‡ ‘*’, ‘+’, ‘’? か 領域 (bound) のいずれかが続いたものです。 アトムに ‘*’ が続いたものは、 そのアトムの 0 個以上のシーケンスにマッチします。 アトムに ‘+’ が続いたものは、 そのアトム 1 個以上のシーケンスにマッチします。 アトムに ‘’? が続いたものは、 そのアトムの 0 個か 1 個のシーケンスにマッチします。

領域 は ‘{’ で始まり、符号なしの 10 進数の整数が続き、 その次に ‘’, が続くことがあり、 またその次にもうひとつ符号なしの 10 進数の整数が続くことがあり、 最後には常に ‘}’ が続きます。 ここでの整数は 0 から RE_DUP_MAX (255‡) の範囲 (これらの数値を含む) でなくてはならず、 数値が 2 つある場合は、 最初のものは 2 番目のもの以下でなければなりません。 ひとつの整数値 i が含まれコンマが含まれない領域がアトムに続くと、 アトムがちょうど i 個のシーケンスにマッチします。 ひとつの整数値 i とコンマが含まれる領域がアトムに続くと、 i 個以上のアトムのシーケンスにマッチします。 2 つの整数値 i と j が含まれる領域がアトムに続くと、 i 個以上 j 個以下のアトムからなるシーケンスにマッチします。

アトムは次のいずれかです: ‘()’ に囲まれた正規表現 (その正規表現にマッチ)、 ‘()’ の空のセット (ヌルストリングにマッチ)‡、 角括弧式 (下記参照)、 ‘’. (任意の 1 文字にマッチ)、 ‘^’ (行の先頭のヌルストリングにマッチ)、 ‘$’ (行の末尾のヌルストリングにマッチ)、 ‘\’ とそれに続く ‘^.[$()|*+?{\’ の内のどれか 1 文字 (それらの通常の扱いでの文字にマッチ)、 ‘\’ とそれに続くその他の文字‡ (それらの通常の扱いでの文字にマッチ、 ‘\’ がない場合と同様‡)、 もしくはその他に何も指定されていない文字 (その文字にマッチ)。 ‘{’ に数字以外の文字が続くものは通常の文字であり、 領域の開始とはなりません‡。 ‘\’ で終了する正規表現は規則違反となります。

角括弧式 (bracket expression) とは ‘[]’ で囲まれた文字のリストです。 通常はリスト中のどれか 1 文字にマッチします (下記を除く)。 リストの最初が ‘^’ で始まる場合、 リストの残りの文字 でない 1 文字にマッチします (下記を除く)。 リスト中の 2 文字が ‘-’ で分割されている場合は、 これら 2 文字の 範囲 (その 2 文字を含む) にある文字の省略形となり、 例えば ASCII では ‘[0-9]’ は 10 進数数字にマッチします。 ‘a-c-e’ のように 2 つの文字範囲がひとつの文字を共有することはできません‡。 文字範囲は文字コードの配列に非常に依存しており、 移植性の良いプログラムを書くにはこれに頼ることを避けるのが賢明でしょう。

リスト中に文字 ‘’] を含めるには、これを最初の文字にする (もしくは ‘^’ に続ける) ようにします。 文字 ‘-’ を含めるには、これを最初もしくは最後の文字にするか、 文字範囲の終了文字とします。 文字 ‘-’ を文字範囲の開始文字とするには、 これを連続要素とするために ‘[.’ と ‘.]’ で括ります (下記参照)。 これらと ‘[’ を使用したいくつかの組合せの例外を除いて、 ‘\’ を含むすべての他の特殊文字は角括弧式の中では それらの特殊な作用は無効となります。

角括弧式の中では、連続要素 (文字、1 文字のように扱われる複数文字からなるシーケンス、 またはそれら連続シーケンスの名称) は、 ‘[.’ と ‘.]’ で括られ、 その連続要素の文字のシーケンスの意味となります。 このシーケンスは角括弧式のリストのひとつの要素となります。 複数文字からなる連続要素を含む角括弧式はこのように 1 文字以上のものに マッチすることができます。 例えば、連続シーケンスが連続要素として ‘ch’ を含む場合、 正規表現 ‘[[.ch.]]*c’ は ‘chchcc’ の最初の 5 文字にマッチします。

角括弧式の中では、 ‘[=’ と ‘=]’ で囲まれた連続要素は ひとつの等価クラスであり、 それ自身を含むすべての連続要素の文字のシーケンスを示しています。 (もしその他に等価な連続要素がない場合は、 それはそれを囲うものが ‘[.’ と ‘.]’ であるもののように扱われます。) 例えば、 ‘x’ と ‘y’ が等価クラスのメンバである時、 ‘[[=x=]]’ と ‘[[=y=]]’ と ‘[xy]’ はすべて同じ意味を持ちます。 等価クラスは文字範囲の終了点とすることはできません‡。

角括弧式の中では、 ‘[:’ と ‘:]’ で囲まれた 文字クラス の名称は そのクラスに属するすべての文字のリストを表わします。 標準の文字クラスの名称には次のものがあります。

alnum | digit | punct
alpha | graph | space
blank | lower | upper
cntrl | print | xdigit

これらは ctype(3) において定義されている文字クラスを表わしています。 ロケールによってはこれら以外のものがあることがあります。 文字クラスは文字範囲の終了点として使うことは出来ません。

角括弧式には 2 つの特殊なケース‡があります。 角括弧式 ‘[[:<:]]’ と ‘[[:>:]]’ はそれぞれ単語の開始および終了点に おけるヌルストリングにマッチします。 単語は単語文字が前にも後にも付加されない 単語文字のシーケンスとして定義されます。 単語文字は alnum (アルファベットと数字) 文字 ( ctype(3) で定義されているように) か下線文字です。 これは拡張して定義されているもので、 p1003.2 に互換性はありますが、指定はされていません。 この拡張はソフトウェアにおいては、 他のシステムへの移植性をよく考えて使うべきです。

与えられた文字列の複数のサブストリング (文字列の一部) に、ある正規表現がマッチ可能な場合、 その正規表現は文字列の中で最初に現れたものにマッチします。 もし正規表現が同じ位置に現れた複数のサブストリングにマッチする場合は、 最も長いものにマッチします。 サブ式 (subexpression - 式の一部) も最も長いサブストリングにマッチしますが、 マッチ全体が最も長くなるように、 また正規表現中で先に開始しているサブ式が遅く開始しているものより 高い優先度をもつような条件があります。 高いレベルのサブ式はこのため低いレベルの部品的なサブ式より 高い優先度を持ちます。

マッチの長さは連続要素ではなく、文字数で計られます。 ヌルストリングは全くマッチしないものよりは長いものであると考えられます。 例えば、 ‘bb*’ は ‘abbbc’ の 3 つの真中の文字にマッチし、 ‘(wee|week)(knights|nights)’ は ‘weeknights’ の 10 個すべての文字にマッチし、 ‘(.*).*’ が ‘abc’ にマッチする時には、括弧で囲まれたサブ式は 3 つすべての文字にマッチします。 そして ‘(a*)*’ が ‘bc’ にマッチする時には、 正規表現全体と括弧で囲まれたサブ式の両方がヌルストリングにマッチします。

ケース (大文字/小文字) 非依存マッチが指定された場合、 アルファベットからケースの区別がすべて消え去ったような効果があります。 ケースが複数あるアルファベットが角括弧式の外に通常の文字として現れた時、 それは事実上すべてのケースを含む角括弧式 (たとえば ‘x’ は ‘[xX]’ に) に変換されます。 角括弧式の中に現れたときは、 その文字の異なるケースがその角括弧式に追加されます。 すなわち ‘[x]’ は ‘[xX]’ となり、また ‘[^x]’ は ‘[^xX]’ となります。

正規表現の長さは特に制限は設けられていません‡。 プログラムに移植性を持たせたい場合は 正規表現は 256 バイトにとどめるべきでしょう。 256 バイトを越える正規表現の受理を拒否するにもかかわらず、 POSIX 準拠であるとする実装がありうるからです。

旧式 (“基本”) 正規表現はいくつかの点で異なっています。 ‘|’ は通常の文字であり、 これらの機能の等価なものは存在しません。 ‘+’ や ‘’? は通常の文字であり、それらの機能は 領域を用いて表されます (それぞれ ‘{1,}’ または ‘{0,1}’) 。 また、現代正規表現の ‘x+’ は ‘xx*’ と等価であることに注意して下さい。 領域の区切り文字は ‘\{’ と ‘\}’ であり、 ‘{’ と ‘}’ は通常の文字として扱われます。 ネストしたサブ式での括弧は ‘\(’ と ‘\)’ であり、 ‘(’ と ‘’) は通常の文字となります。 ‘^’ は正規表現の先頭、もしくは‡ 括弧で囲まれたサブ式の先頭を除いて通常の文字となり、 ‘$’ は正規表現の末尾、もしくは‡ 括弧で囲まれたサブ式の末尾を除いて通常の文字となり、 ‘*’ はもしこれが正規表現の先頭、もしくは括弧で囲まれたサブ式の先頭 (か、先頭の ‘^’ のあと) に現れると通常の文字となります。 最後にひとつ新しい型のアトム - 後方参照 があります。 ‘\’ に 0 でない 10 進数 d が続いたものは、 d 番目の括弧で囲まれたサブ式によってマッチする文字の同じ シーケンスにマッチします (開き括弧の位置によって左から右へサブ式に番号を付けます)。 すなわち ‘\([bc]\)\1’ は ‘bb’ や ‘cc’ にマッチしますが、 ‘bc’ にはマッチしません。

関連項目
regex(3) Regular Expression Notation, IEEE Std, 1003.2, section 2.8.

バグ
正規表現が 2 種類もあるのはへまなことです。

現在の p1003.2 仕様では ‘’) はマッチする ‘(’ がない場合に 普通の文字として扱われることになっています。 これは言葉使い上の誤りの意図しない結果であり、 変更される可能性があります。 よって、この仕様に依存すべきではありません。

後方参照はひどいへまであり、 効率的な実装をおこなう上で大きな問題を引き起こします。 さらに、それらの定義はどこかあいまいです。( ‘a\(\(b\)*\2\)*d’ は ‘abbbd’ にマッチするでしょうか ?) これらを使うのは避けてください。

p1003.2 のケース非依存マッチの仕様はあいまいです。 上記での “ひとつのケースはすべてのケースを表わす” という定義は 実装を行ったものの間では正しい解釈として現在同意されているものです。

語の境界の構文は信じられないほど醜いものです。