9.7. パターンマッチ

PostgreSQLには、パターンマッチを行うに際して3つの異なった手法があります。伝統的なSQLLIKE演算子、これより新しいSIMILAR TO演算子(SQL:1999で追加されました)、およびPOSIX様式の正規表現です。基本の"この文字列はこのパターンにマッチするか?"を別としても、マッチした部分文字列を取り出したり置換したり、そしてそのマッチによる文字列分割の関数が用意されています。

ティップ: 上記の手法では検索できないようなパターンマッチが必要な場合は、PerlもしくはTclでユーザ定義関数を作成することを検討してください。

9.7.1. LIKE

string LIKE pattern [ESCAPE escape-character]
string NOT LIKE pattern [ESCAPE escape-character]

それぞれのpatternは、文字列の集合を定義します。LIKE式はpatternによって示される文字列の集合にstringが含まれていれば真を返します(想像される通り、NOT LIKE式はLIKE式が真を返す場合には偽を返し、その逆もまた同じです。同等の式としてNOT (string LIKE pattern)とも表現できます)。

patternがパーセント記号もしくはアンダースコアを含んでいない場合patternは自身の文字列そのものです。この場合LIKE式は等号演算子のように振舞います。patternの中にあるアンダースコア(_)は任意の一文字とのマッチを意味し、パーセント記号(%)は0文字以上の文字列とのマッチを意味します。

例:

'abc' LIKE 'abc'    true
'abc' LIKE 'a%'     true
'abc' LIKE '_b_'    true
'abc' LIKE 'c'      false

LIKEによるパターンマッチは常に文字列全体に対して行われます。 ですから、文字列内の任意位置における並びとマッチさせるにはパーセント記号を先頭と末尾に付ける必要があります。ですから、文字列内の任意位置における並びとマッチさせるにはパーセント記号を先頭と末尾に付ける必要があります。

アンダースコアやパーセント記号というリテラルを他の文字のマッチに使用するのではなく、そのものにマッチさせたい場合には、patternの中のそれぞれのアンダースコアとパーセント記号の前にエスケープ文字を付けなければなりません。デフォルトのエスケープ文字はバックスラッシュですが、ESCAPE句で他の文字を指定することができます。エスケープ文字そのものをマッチさせるにはエスケープ文字を2つ書きます。

リテラル文字列においてバックスラッシュには始めから特別な意味合いがあるので、バックスラッシュを含んだパターン定数を記述する時は問い合わせの中で2つのバックスラッシュを記述する必要があることに注意してください(エスケープ文字列構文の使用を前提)。 したがって、実際にバックスラッシュそのものにマッチするパターンを記述するには、文の中でバックスラッシュを4つ記述する必要があります。ESCAPE句で他のエスケープ文字を選択すればこのような状況を回避でき、バックスラッシュはLIKE式にとって特殊な文字ではなくなります(とは言っても、リテラル文字列パーサにとっては依然として特殊文字なので、やはり2つは必要です)。

同時にESCAPE ''と記述することでエスケープ文字を選択しないことも可能です。 これにより、事実上エスケープ機構が働かなくなります。つまり、パターン内のアンダースコアおよびパーセント記号の特別な意味を解除することはできなくなります。

現在のロケールに従って大文字小文字を区別しないマッチを行うのであれば、LIKEの代わりにILIKEキーワードを使うことができます。これは標準SQLではなく、PostgreSQLの拡張です。

~~演算子はLIKE式と等価で、~~*ILIKEに対応します。またNOT LIKEおよびNOT ILIKEを表す!~~および!~~*演算子があります。これら全ての演算子はPostgreSQL固有のものです。

9.7.2. SIMILAR TO正規表現

string SIMILAR TO pattern [ESCAPE escape-character]
string NOT SIMILAR TO pattern [ESCAPE escape-character]

SIMILAR TO演算子は、そのパターンが与えられた文字列にマッチするかどうかにより、真もしくは偽を返します。これは、標準SQLの正規表現定義を使用してパターンを解釈するという点以外は、LIKEに非常によく似ています。SQLの正規表現は、LIKE表記と一般的な正規表現の表記とを混ぜ合わせたようなものになっています。

LIKEと同様、SIMILAR TO演算子は、そのパターンが文字列全体にマッチした場合のみ処理を行います。これは、パターンが文字列の一部分であってもマッチする、一般的な正規表現の処理とは異なっています。また、LIKEと同様、SIMILAR TOでは、%および_を、それぞれ任意の文字列および任意の単一文字を意味するワイルドカード文字として使用します(これらは、POSIX正規表現での.*および.に相当します)。

LIKEから取り入れた上記の機能に加え、SIMILAR TOでは、以下のようにPOSIX正規表現から取り入れたパターンマッチメタ文字もサポートしています。

バウンド反復(?および{...})は、POSIXにはありますが、ここでは使用できないことに注意してください。また、ドット(.)はメタ文字ではありません。

LIKEと同様、バックスラッシュは全てのメタ文字の特殊な意味を無効にします。 また、異なるエスケープ文字をESCAPEで指定することが可能です。

例:

'abc' SIMILAR TO 'abc'      true
'abc' SIMILAR TO 'a'        false
'abc' SIMILAR TO '%(b|d)%'  true
'abc' SIMILAR TO '(b|c)%'   false

3つのパラメータを持つsubstring関数、substring(string from pattern for escape-character)を使用して、SQL正規表現パターンにマッチする部分文字列を取り出すことができます。SIMILAR TOと同様、指定したパターンがデータ文字列全体にマッチする必要があります。マッチしない場合、関数は終了し、NULLを返します。マッチした場合に返されるべきパターンの一部を示すために、エスケープ文字の後に二重引用符(")を繋げたものを2つパターンに含める必要があります。これらの印で括られたパターンの一部にマッチするテキストが返されます。

例:

substring('foobar' from '%#"o_b#"%' for '#')   oob
substring('foobar' from '#"o_b#"%' for '#')    NULL

9.7.3. POSIX正規表現

表9-11に、POSIX正規表現を使ったパターンマッチングに使用可能な演算子を列挙します。

表 9-11. 正規表現マッチ演算子

演算子説明
~ 正規表現にマッチ、大文字小文字の区別あり'thomas' ~ '.*thomas.*'
~* 正規表現にマッチ、大文字小文字の区別なし'thomas' ~* '.*Thomas.*'
!~ 正規表現にマッチしない、大文字小文字の区別あり'thomas' !~ '.*Thomas.*'
!~* 正規表現にマッチしない、大文字小文字の区別なし'thomas' !~* '.*vadim.*'

POSIX正規表現は、パターンマッチという意味合いでは、LIKEおよびSIMILAR TO演算子よりもさらに強力です。egrepsed、あるいはawkのような多くのUnixツールはここで解説しているのと類似したパターンマッチ言語を使用しています。

正規表現とは文字列の集合(正規集合)の簡略された定義である文字が連なっているものです。ある文字列が正規表現で記述された正規集合の要素になっていれば、その文字列は正規表現にマッチしていると呼ばれます。LIKEと同様、正規表現言語で特殊文字とされているもの以外、パターン文字は文字列と完全にマッチされます。とは言っても、正規表現はLIKE関数が使用するものと異なる特殊文字を使用します。LIKE関数のパターンと違って正規表現は、明示的に正規表現が文字列の最初または最後からと位置指定されていない限り文字列内のどの位置でもマッチを行えます。

例:

'abc' ~ 'abc'    true
'abc' ~ '^a'     true
'abc' ~ '(b|d)'  true
'abc' ~ '^(b|c)' false

POSIXパターン言語について以下により詳しく説明します。

2つのパラメータを持つsubstring関数、substring(string from pattern)を使用して、POSIX正規表現パターンにマッチする部分文字列を取り出すことができます。この関数は、マッチするものがない場合にはNULLを返し、ある場合はパターンにマッチしたテキストの一部を返します。しかし、任意の丸括弧を持つパターンの場合、最初の丸括弧内部分正規表現(左丸括弧が最初に来るもの)にマッチするテキストの一部が返されます。この例外を起こさずにパターン中に丸括弧を使用したいのであれば、常に正規表現全体を丸括弧で囲むことができます。パターン内の抽出対象の部分文字列より前に丸括弧が必要な場合、後述の捕捉されない丸括弧を参照してください。

例:

substring('foobar' from 'o.b')     oob
substring('foobar' from 'o(.)b')   o

regexp_replace関数は、POSIX正規表現パターンにマッチする部分文字列を新規テキストと置換します。 構文は、regexp_replacesourcepatternreplacement [flags ])です。 patternにマッチしない場合は、source文字列がそのまま返されます。 マッチすると、マッチ部分文字列をreplacement文字列で置換したsource文字列が返されます。 replacement\nを含むことができます。 ここでnは、n番目に丸括弧で括られたパターンの部分表現にマッチする元の部分文字列を示す、 1から9までの数です。 \&が含まれた場合、パターン全体とマッチする部分文字列が挿入されることを示します。 置換テキスト内にリテラルバックスラッシュを挿入する必要にある時は\\と記述します。 (いつもの通り、エスケープ文字列構文の使用を前提すると、リテラル定数文字列内ではバックスラッシュを2重にすることを思いだしてください。) flagsパラメータは、関数の振る舞いを変更するゼロもしくはそれ以上の1文字フラグを含むオプションのテキスト文字列です。フラグiは大文字小文字を区別したマッチングを指定する一方、フラグgは、最初にマッチしたもののみではなく、それぞれマッチした部分文字列の置換を指定します。その他の有効なフラグは表9-19に記述されています。

例:

regexp_replace('foobarbaz', 'b..', 'X')
                                   fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
                                   fooXX
regexp_replace('foobarbaz', 'b(..)', E'X\\1Y', 'g')
                                   fooXarYXazY

regexp_matches関数はPOSIX正規表現パターンマッチの結果捕捉された全ての部分文字列を返します。regexp_matches(string, pattern [, flags ])の構文になります。 もしpatternに対してマッチしない場合、関数は行を返しません。マッチする場合、関数はパターンのn番目に丸括弧で括られた部分文字列にマッチする、n番目の要素が部分文字列であるテキスト配列を返します("捕捉されない"丸括弧は数えません)。パターンが丸括弧に括られた部分文字列を含まない場合、結果はパターン全体にマッチする部分文字列を含む単一要素のテキスト配列となります。flagsパラメータは、関数の振る舞いを変更するゼロもしくは複数の単一文字フラグを含むオプションのテキスト文字列です。フラグgは関数に、最初のマッチだけでなく文字列の中で全てのマッチを検出させ、それらマッチの行を返させます。その他有効なフラグは表9-19に記載されています。

例:

SELECT regexp_matches('foobarbequebaz', '(bar)(beque)');
 regexp_matches 
----------------
 {bar,beque}
(1 row)

SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g');
 regexp_matches 
----------------
 {bar,beque}
 {bazil,barf}
(2 rows)

SELECT regexp_matches('foobarbequebaz', 'barbeque');
 regexp_matches 
----------------
 {barbeque}
(1 row)

regexp_split_to_table関数はPOSIX正規表現パターンを区切り文字として使用し、文字列を分割します。regexp_split_to_table(string, pattern [, flags ])の構文になります。patternにマッチしない場合、関数はstringを返します。少なくともひとつのマッチがあれば、それぞれのマッチに対して関数は最後のマッチの終わり(あるいは文字列の始め)から最初のマッチまでのテキストを返します。もはやマッチしなくなると最後のマッチの終わりから文字列の最後までテキストを返します。 flagsパラメータは、関数の振る舞いを変更するゼロもしくは複数の単一文字フラグを含むオプションのテキスト文字列です。regexp_split_to_table表9-19で記載されているフラグをサポートします。

regexp_split_to_array関数は、regexp_split_to_arrayがその結果をtext配列で返すことを除いて、regexp_split_to_tableと同じ振る舞いをします。regexp_split_to_array(string, pattern [, flags ])の構文になります。

例:


SELECT foo FROM regexp_split_to_table('the quick brown fox jumped over the lazy dog', E'\\\s+') AS foo;
  foo   
--------
 the    
 quick  
 brown  
 fox    
 jumped 
 over   
 the    
 lazy   
 dog    
(9 rows)

SELECT regexp_split_to_array('the quick brown fox jumped over the lazy dog', E'\\s+');
              regexp_split_to_array             
------------------------------------------------
 {the,quick,brown,fox,jumped,over,the,lazy,dog}
(1 row)

SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo;
 foo 
-----
 t         
 h         
 e         
 q         
 u         
 i         
 c         
 k         
 b         
 r         
 o         
 w         
 n         
 f         
 o         
 x         
(16 rows)

最後の例が明らかにしているように、regexp分割関数は文字列の最初あるいは終わり、もしくは前のマッチの直後に発生する長さを持たないマッチを無視します。regexp_matchesで実装されたregexpマッチの厳格な定義にこれは相容れませんが、実務上は最も使い勝手の良い振る舞いです。Perlのような他のソフトウェアシステムも似たような定義を使用します。

9.7.3.1. 正規表現の詳細

PostgreSQLの正規表現はHenry Spencerにより書かれたパッケージを使用して実装されています。以下に説明する正規表現の多くの部分は同氏のマニュアル項目から一字一句複製したものです。

POSIX 1003.2の定義によると、正規表現(RE)には2つの形式があるとされます。拡張REもしくはERE(大まかにいってegrepに代表されるもの)、および基本REもしくはBRE(大まかにいってedに代表されるもの)です。PostgreSQLは両方の形式をサポートし、さらに、POSIX標準にはないけれどもPerlやTclなどのプログラミング言語で利用できることから広く使用されるようになった、いくつかの拡張もサポートしています。本書では、非POSIX拡張を使用したRE高度なREもしくはAREと呼びます。AREはEREの正確な上位セットですが、BREとは複数の記法上の非互換な点があります(さらに非常に多くの制限が課されています)。まず、AREとERE形式について説明し、そして、AREにのみ適用される機能の注意を、さらにBREとの違いについて説明します。

注意: PostgreSQLで受け入れられる正規表現の形式はregex_flavor実行時パラメータの設定で選択することができます。通常の設定はadvancedです。しかし、extendedを選択して、PostgreSQLリリース7.4より前のリリースとの後方互換性を最大にすることもできます。

正規表現は|で区切られた、1つまたは複数のブランチとして定義されます。ブランチのいずれか1つにマッチすればマッチしたことになります。

ブランチはゼロ個以上の量化アトムもしくは制約の連結です。最初のものにマッチし、その次にマッチし、というふうにマッチされます。なお、空のブランチは空文字列にマッチします。

量化アトムとは、単一の量指定子が後ろに付くアトムのことです。量指定子がないと、アトムに一致するものがマッチしたことになります。量指定子がある場合、アトムとの一致が何回あるかでマッチしたことになります。アトムは、表9-12に示したもののいずれかを取ることができます。表9-13に設定可能な量指定子とその意味を示します。

制約は空文字に、特定の条件に合う場合のみにマッチします。アトムが使用できる所で制約を使用することができます。ただし、その後に量指定子を付けることはできません。単純な制約を表9-14に示します。後で他のいくつかの制約を説明します。

表 9-12. 正規表現のアトム

アトム説明
(re) (ここでre は任意の正規表現で、)reとのマッチに適合するもです。 マッチは可能である報告用と意味づけられます。
(?:re) 上と同じ。ただし、マッチは報告用と意味づけられません。("捕捉されない"括弧の集合)(AREのみ)
. 任意の1文字にマッチします。
[chars] ブラケット式charsのいずれか1つにマッチします (詳細は項9.7.3.2を参照してください)。
\k (ここでkは英数字以外です。)普通の文字として指定した文字にマッチします。 例えば、\\はバックスラッシュ文字です。
\c ここでcは英数字です (おそらく他の文字が後に続きます)。 エスケープです。 項9.7.3.3を参照してください (AREのみ、EREとBREではこれはcにマッチします)。
{ 直後に数字以外がある場合、左中括弧{にマッチします。 直後に数字が続く場合、bound(後述)の始まりです。
x ここでxは他に意味を持たない1文字です。 xにマッチします。

REは\を終端とすることはできません。

注意: PostgreSQLの文字列リテラル内のバックスラッシュ(\)が既に特別な意味を持っていることを忘れないでください。 エスケープ文字列構文が使用されると仮定すると、バックスラッシュを含むパターン定数を書く時には、その命令文では2つのバックスラッシュを書かなければなりません(項4.1.2.1を参照ください)。

表 9-13. 正規表現量指定子

量指定子マッチ
* アトムの0個以上複数の並びにマッチ
+ アトムの1個以上複数の並びにマッチ
? アトムの0個または1個の並びにマッチ
{m} アトムの正確にm個の並びにマッチ
{m,} アトムのm個以上の並びにマッチ
{m,n} アトムのm個以上n以下の並びにマッチ。 mnを超えることはできません。
*? *の最短マッチを行うバージョン
+?  
?? ?の最短マッチを行うバーション
{m}? {m}の最短マッチを行うバージョン
{m,}? {m,}の最短マッチを行うバーション
{m,n}? non-greedy version of {m,n}

{...}を使用する形式はバウンドとして知られています。バウンド内のmnという数は符号なし10進整数であり、0以上255以下の値を取ることができます。

最短マッチを行う量指定子(AREのみで使用可能)は、対応する通常の(欲張りの)ものと同じものにマッチしますが、最大のマッチではなく最小のマッチを取ります。 詳細は項9.7.3.5を参照してください。

注意: 量指定子の直後に量指定子を続けることはできません。 量指定子から式や副式を始めることはできず、また、^|の直後に付けることもできません。

表 9-14. 正規表現制約

制約説明
^ 文字列の先頭にマッチ
$ 文字列の末尾にマッチ
(?=re) 先行肯定検索は、reにマッチする部分文字列から始まる任意の場所にマッチします(AREのみ)。
(?!re) 先行否定検索は、reにマッチしない部分文字列から始まる任意の場所にマッチします(AREのみ)。

先行検索制約には後方参照項9.7.3.3を参照)を含めることはできません。また、その中の括弧は全て取り込むものではないとみなされます。

9.7.3.2. ブラケット式

ブラケット式とは、[]内の文字のリストです。通常これはそのリスト内の任意の1文字にマッチします(しかし、以降を参照してください)。リストが^から始まる場合、そのリストの残りにはない任意の1文字にマッチします。リスト内の2文字が-で区切られていた場合、これは2つ(を含む)の間にある文字範囲全体を表す省略形となります。例えば、ASCIIにおける[0-9]は全ての数字にマッチします。例えばa-c-eといった、終端を共有する2つの範囲は不正です。範囲は並びの照合順に非常に依存しています。ですので、移植予定のプログラムではこれに依存してはなりません。

このリストに]そのものを含めるには、それを先頭文字(もしあれば^の後の文字)にしてください。-そのものを含めるには、それを先頭もしくは末尾の文字とするか、範囲の2番目の終端としてください。-を範囲の1番目の終端で使用するには、[..]でそれを囲み、照合要素(後述)にしてください。これらの文字には例外があり、[(次段落を参照)、エスケープ(AREのみ)、他の全ての特殊文字の組み合わせはブラケット式内では特殊な意味を持ちません。特に、\はEREとBRE規則に従う場合は特別でなくなります。しかし、AREでは(エスケープの始まりとして)特別な意味を持ちます。

ブラケット式内に、照合要素(文字、単一文字であるかのように照合する複数文字の並び、もしくはそれぞれの照合並びの名前)が[..]の間にあると、その照合要素の文字の並びを意味します。この並びはブラケット式のリストの一要素です。こうして、要素を照合する複数文字を含むブラケット式は1文字以上にマッチすることができます。例えば、照合並びがch照合要素を含む場合、正規表現[[.ch.]]*cchchccという文字の最初の5文字にマッチします。

注意: 今のところ、PostgreSQLは複数文字照合要素を持ちません。この情報は将来の振舞いの可能性を説明したものです。

ブラケット式内の[==]の間に照合要素は同値クラスです。全ての照合要素の文字の並びが自身を含むものと等価であることを示します(他に等価な照合要素がある場合、[..]で囲まれたかのように扱われます)。例えば、[[=o=]][[=^=]]および[o^]が全て同意語であれば、o^は同値クラスのメンバです。同値クラスは範囲の終端にはなりません。

ブラケット式内では、[::]の間にある文字クラスの名称は、そのクラスに属する全ての文字のリストを意味します。標準文字クラス名は、alnumalphablankcntrldigitgraphlowerprintpunctspaceupperxdigitです。これらはctypeで定義された文字クラスを意味します。ロケールは別のものを提供可能です。文字クラスは範囲の終端では使用することができません。

ブラケット式には2つの特殊な場合があります。[[:<:]][[:>:]]というブラケット式は、先頭と終端の単語がそれぞれ空文字であることにマッチする制約です。単語は、単語文字が前後に付かない単語文字の並びとして定義されます。単語文字とは1つのalnum文字です(ctypeで定義されています)。これは、POSIX 1003.2との互換性はありますが、そこでは定義されていない式です。ですので、他システムへ移植予定のソフトウェアでの使用には注意が必要です。通常後述の制約エスケープの方がよく使われます(これも標準ではありませんが、入力しやすくなっています)。

9.7.3.3. 正規表現エスケープ

エスケープとは、\から始まり英数字がその後に続く特殊な並びです。エスケープには、文字エントリ、クラス省略、制約エスケープ、後方参照といった様々な変種があります。\の後に英数字が続くけれども、有効なエスケープを構成しない並びはAREでは不正です。EREにはエスケープはありません。ブラケット式の外側では、\の後に英数字が続く並びは単に普通の文字としてその文字を意味します。ブラケット式の内側では、\は普通の文字です(この文字はEREとARE間の非互換性の1つです)。

文字エントリエスケープは非印字文字やRE内で不便な文字の指定を簡略化するために存在します。これらを表9-15に示します

クラス省略エスケープは、あるよく使用される文字クラスの省略形を提供します。これらを表9-16に示します。

制約エスケープは、指定した条件に合う場合に空文字にマッチする制約をエスケープとして表したものです。これらを表9-17に示します。

後方参照\n)は、直前に括弧で囲まれた副式によってマッチされた、n番目の同一文字列にマッチします(表9-18を参照してください)。例えば、([bc])\1bbもしくはccにマッチしますが、bccbにはマッチしません。REでは副式全体は後方参照の前になければなりません。副式は開括弧の順番で番号付けされます。取り込まない括弧は副式を定義しません。

注意: エスケープの先頭の\をSQL文字定数としてパターンに入力する時には二重にしなければならないことを忘れないでください。以下に例を示します。

'123' ~ E'^\\d{3}' true

表 9-15. 正規表現文字エントリエスケープ

エスケープ説明
\a C言語と同じ警報(ベル)文字
\b C言語と同じバックスペース
\B バックスラッシュの必要な二重化回数を減らすための\の同義語
\cX (ここでXは任意の文字で)その下位5ビットがXと同一、その他のビットが0となる文字
\e 照合順名がESCとなる文字、それに失敗したら、033という8進数値を持つ文字。
\f C言語と同じ改ページ
\n C言語と同じ改行
\r C言語と同じ復帰
\t C言語と同じ水平タブ
\uwxyz (ここでwxyzは正確に4桁の16進数で)使用マシンのバイト順で表した、U+wxyzというUTF16(16ビット、Unicode)文字
\Ustuvwxyz (ここでstuvwxyzは正確に8桁の16進数です。)何らかの仮定のために確保されたUnicode拡張、32ビット
\v C言語と同じ垂直タブ
\xhhh (ここでhhhは任意の16進数の並びで)その文字の16進数値が0xhhhとなる文字(使用される16進数の桁数にかかわらず単一の文字)
\0 その値が0となる文字
\xy (ここでxyは正確に2桁の8進数で、後方参照ではない)その値が0xyとなる文字
\xyz (ここでxyzは正確に3桁の8進数で、後方参照ではない)その値が0xyzとなる文字

16進数の桁とは0-9a-fA-Fです。8進数の桁とは0-7です。

この文字エントリエスケープは常に普通の文字と解釈されます。例えば、\135はASCIIの]となり、\135はブラケット式の終端にはなりません。

表 9-16. 正規表現クラス省略エスケープ<

エスケープ説明
\d [[:digit:]]
\s [[:space:]]
\w [[:alnum:]_] (note underscore is included)
\D [^[:digit:]]
\S [^[:space:]]
\W [^[:alnum:]_] (アンダースコアが含まれることに注意)

ブラケット式内では、\d\s、および\wはその外側の大括弧を失い、\D\Sおよび\Wは不正です(ですから、例えば[a-c\d][a-c[:digit:]]と同じになります。また、[a-c\D][a-c^[:digit:]]と同じになり、不正です)。

表 9-17. 正規表現制約エスケープ

エスケープ説明
\A 文字列の先頭にのみマッチします(^との違いについては項9.7.3.5を参照してください)。
\m 単語の先頭にのみマッチします。
\M 単語の末尾にのみマッチします。
\y 単語の先頭もしくは末尾にのみマッチします。
\Y 単語の先頭もしくは末尾以外の場所にのみマッチします。
\Z 文字列の末尾にのみマッチします($との違いについては項9.7.3.5を参照してください)。

単語は前述の[[:<:]][[:>:]]の規定通りに定義されます。ブラケット式内では制約エスケープは不正です。

表 9-18. 正規表現後方参照

エスケープ説明
\m (ここでmは非ゼロの数です。)副式のm番目への後方参照
\mnn (ここでmは非ゼロの数です。nnでさらに桁を指定します。mnn10進数値は取り込み括弧の数よりも多くてはなりません。)副式のmnn番目への後方参照

注意: 8進数の文字エントリエスケープと後方参照の間には歴史的な曖昧性があります。上でヒントとして示したようにこれは発見的手法で解決されます。先頭の0は常に8進数エスケープを示します。その後に数字が続かない単一の非ゼロ数字は常に後方参照として解釈されます。ゼロから始まらない複数数字の並びは、適切な副式の後にあれば(つまり、その番号が後方参照用の範囲内にあれば)後方参照として解釈されます。さもなくば、8進数として解釈されます。

9.7.3.4. 正規表現メタ構文

上述の主構文の他に、特殊な形式や雑多な構文的な機能が使用可能です。

通常、使用されるREの種類はregex_flavorで決定されます。しかし、決定子前置詞によって上書きすることができます。REが***:から始まるものであれば、regex_flavorに関係なく、REの残りはAREと解釈されます。REが***=から始まるものであれば、REの残りは、全ての文字を普通の文字とみなしたリテラル文字列と解釈されます。

AREは埋め込みオプションから始められます。(?xyz)という並びで残りのREに影響するオプションを指定します(ここでxyzは1つ以上の英字です)。このオプションは、事前に決定された(RE種類や大文字小文字の区別を含む)オプションを上書きします。使用可能なオプション文字を表9-19に示します。

表 9-19. ARE埋め込みオプション文字

オプション説明
b 残りのREはBRE
c 大文字小文字を区別するマッチ(演算子で規定される大文字小文字の区別よりこの指定が優先されます)。
e 残りのREはERE
i 大文字小文字を区別しないマッチ(項9.7.3.5を参照)(演算子で規定される大文字小文字の区別よりこの指定が優先されます)。
m nの歴史的な同義語
n 改行を区別するマッチ(項9.7.3.5を参照)
p 部分的な改行を区別するマッチ(項9.7.3.5を参照)
q 残りのREはリテラル("引用符付けされた")文字列、全て普通の文字
s 改行を区別しないマッチ(デフォルト)
t 厳しめの構文(デフォルト、後述)
w 部分的な改行区別の逆("ワイアード")マッチ(項9.7.3.5を参照)
x 拡張構文(後述)

埋め込みオプションはその並びの終端)で有効になります。AREの先頭(もし***:決定子があればその後)でのみ利用可能です。

全ての文字が意味を持つ、通常の(厳しめの)RE構文に加え、x埋め込みオプションを指定することで利用できる拡張構文があります。拡張構文では、RE内の空白文字は無視され、#とその後の改行(もしくはREの終端)の間の全ての文字も同様です。これにより、段落付けや複雑なREのコメント付けが可能になります。基本規則に対して3つの例外があります。

  • 直前に\が付いた空白文字もしくは#は保持されます。

  • ブラケット式内の空白文字もしくは#は保持されます。

  • (?:などの複数文字シンボルでは、空白文字とコメントは不正です。

ここでの空白文字とは、空白、タブ、改行、スペース文字クラスに属する文字です。

最後に、AREのブラケット式の外側では、(?#ttt)という並びはコメントになります(ここでttt)を含まない任意のテキストです)。繰り返しになりますが、これは(?:などの複数文字シンボルの文字間では使用できません。こうしたコメントは実用性というより歴史的所産です。そのため、この使用は勧めません。代わりに拡張構文を使用してください。

初めに***=決定子が指定され、ユーザの入力がREではなくリテラルとして扱われる場合、これらのメタ構文拡張は使用できません

9.7.3.5. 正規表現マッチ規則

REが文字列の中の1つ以上の部分文字列とマッチする場合において、REは最初にマッチが始まった部分文字列とマッチします。その位置からまた1つ以上の部分文字列とマッチした際は、正規表現は最短マッチを行わない(欲張り型)最短マッチを行う(非欲張り型)かによって、最長一致もしくは最短一致の文字列のどちらにマッチします

REが欲張り型か、非欲張り型かは以下の規則によって決まります。

  • ほとんどのアトムおよび全ての式は欲張り属性を持ちません(これらは変動する量のテキストにまったくマッチしないからです)。

  • REを括弧で括ることは欲張りかどうかを変更しません。

  • {m}もしくは{m}?といった固定繰り返し数の量指定子を持つ量指定付きアトムは、アトム自身と同一の欲張りさを持ちます(まったく持たない可能性もあります)。

  • 他の通常の量指定子({m,n}mnが等しい場合も含みます)を持つ量指定付きアトムは欲張り型です(最長マッチを使用します)。

  • 他の非欲張り型量指定子({m,n}?mnが等しい場合も含みます)を持つ量指定付きアトムは非欲張り型です(最短マッチを使用します)。

  • 最上位レベルの|演算子を持たないREであるブランチは、最初の欲張り属性を持つ量指定付きアトムと同一の欲張り属性を持ちます。

  • |演算子で接続された2つ以上のブランチからなるREは常に欲張り型です。

上の規則は、個々の量指定付きアトムだけではなく、量指定付きアトムを複数含むブランチやRE全体の欲張り属性に関連します。つまり、ブランチやRE全体が全体として最長または最短の部分文字列にマッチするという方法でマッチ処理が行われます。全体のマッチの長さが決まると、特定の部分式にマッチする部分がその部分式の欲張り属性によって決まります。この時、RE内でより前にある部分式が後にある部分式よりも高い優先度を持ちます。

この意味の例を示します。

SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
Result: 123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
Result: 1

最初の例では、Y*が欲張り型であるため、REは全体として欲張り型です。マッチはYの位置から始まり、そこから可能な限り最長の文字列にマッチします。つまりY123となります。出力は括弧で括られた部分、つまり123となります。2番目の例では、Y*?が非欲張り型のため、REは全体として非欲張り型です。マッチはYの位置から始まり、そこから可能な限り最短の文字列にマッチします。つまりY1となります。部分式[0-9]{1,3}は欲張り型ですが、決定されたマッチする全体の長さを変更することはできません。したがって、強制的に1にマッチすることになります。

まとめると、REが欲張り型部分式と非欲張り型部分式の両方を持つ場合、全体のマッチ長はRE全体に割り当てられる属性に応じて、最長マッチ長か最短マッチ長のどちらかになります。部分式に割り当てられた属性は、部分式の中でどれだけの量をその部分式の中で"消費"できるかのみに影響します。

{1,1}および{1,1}?量指定子を副式もしくはRE全体に使用して、それぞれ、欲張りか欲張りでないかを強制することが可能です。

マッチの長さは照合要素ではなく文字列で測られます。空文字列はまったくマッチする要素がない文字列よりも長いと考えられます。例えば、bb*abbbcの真中の3文字とマッチし、(week|wee)(night|knights)weeknightsの全ての10文字とマッチし、abcに対して(.*).*がマッチされると、括弧内の部分正規表現は3つの文字全てにマッチし、bcに対して(a*)*がマッチされると、全体のREと括弧内の正規表現は空文字列にマッチします。

もし大文字小文字を区別しないマッチングが指定されると、アルファベット文字の大文字小文字の区別がまったくなくなったのと同じ効果を与えます。ブラケット式の外側にアルファベットの大文字小文字が混ざった通常の文字が出てきた場合、例えば、x[xX]となるように大文字小文字ともにブラケット式に実質的に転換されます。ブラケット式の中に現れた時は、(例えば)[x][xX]となり、また[^x][^xX]となるように、全ての大文字小文字それぞれの対がブラケット式に追加されます。

改行を区別するマッチが指定されると、.^を使用するブラケット式は(REが明示的に調整されていたとしてもマッチが改行をまたがらないようにするために)改行文字にマッチしなくなります。また、^$はそれぞれ改行直後と直前の空文字列にマッチし、さらに、それぞれ文字列の先頭と末尾にマッチします。しかし、AREエスケープの\A\Zは、継続して、文字列の先頭と末尾のみにマッチします。

部分的に改行を区別するマッチが指定されると、.とブラケット式は改行を区別するマッチを行うようになりますが、^$は変更されません。

部分的に改行を区別する逆マッチが指定されると、^$は改行を区別するマッチを行うようになりますが、.とブラケット式は変更されません。これはあまり有用ではありません。対称性のために提供されています。

9.7.3.6. 制限と互換性

本実装ではREの長さに関する制限はありません。しかし、移植性を高めたいプログラムでは、256バイトを超えるREを使用すべきではありません。POSIX互換の実装ではそうしたREでは混乱する可能性があります。

AREの機能のうち、POSIX EREと実質的な非互換性があるのは、\がブラケット式の内側で特殊な意味を失わないという点のみです。他の全てのARE機能は、POSIX EREでは不正、未定義、未指定な効果となる構文を使用しています。決定子の***構文などはBREおよびEREのPOSIX構文にはありません。

多くのARE式はPerlから拝借したものです。しかし、いくつかは整理され、Perlの拡張のいくつかは存在しません。注意すべき非互換性には、\b\B、改行の取り扱いに関する特殊な措置の欠落、改行を区別するマッチに影響する点について補足したブラケット式の追加、括弧と先行検索制約内の後方参照についての制限、最長/最短(最初にマッチするではなく)マッチのセマンティックがあります。

PostgreSQLリリース7.4より前で認知された、AREとERE構文間で大きな非互換が2つあります。

  • AREでは、\の後に英数字が続くものはエスケープもしくはエラーとなります。以前のリリースでは、これは単に、英数字を記述する他の方法でした。これは、大きな問題にはならないはずです。以前のリリースではこうした並びを記述する理由がないからです。

  • AREでは、\[]内でも特別な文字です。したがって、ブラケット式では\\\と記述しなければなりません。

これらの違いによりほとんどのアプリケーションでは問題になることはあまりありませんが、必要に応じてregex_flavorextendedに設定することで回避することができます。

9.7.3.7. 基本正規表現

BREはEREといくつかの面において異なります。 |+?は普通の文字であり、それらの機能と等価なものはありません。 バウンドの区切りは\{\}であり、{}自身は普通の文字です。 副式を入れ子にするための括弧は\(\)であり、()自身は普通の文字です。 ^は、REの先頭にある場合や括弧内の副式の先頭の場合を除き、普通の文字です。 $は、REの末尾にある場合や括弧内の副式の末尾の場合を除き、普通の文字です。 また、*はREの先頭にある場合や括弧内の副式の先頭にある場合には普通の文字になります(その前に^が付いている可能性もあります)。 最後に、1桁の後方参照を使用することができ、また、\<\>はそれぞれ[[:<:]][[:>:]]と同義です。

アダルトレンタルサーバー