PostgreSQLには、パターンマッチを行うに際して3つの異なった手法があります。伝統的なSQLのLIKE
演算子、これより新しいSIMILAR TO
演算子(SQL:1999で追加されました)、およびPOSIX様式の正規表現です。
基本の「この文字列はこのパターンに一致するか?」を別としても、一致した部分文字列を取り出したり置換したり、そして一致部分で文字列を分割する関数が用意されています。
上記の手法では検索できないようなパターンマッチが必要な場合は、PerlもしくはTclでユーザ定義関数を作成することを検討してください。
ほとんどの正規表現検索はとても速く実行されますが、正規表現は処理するのに任意の時間とメモリを使う可能性があります。 悪意のあるソースから正規表現検索パターンを受け取ることに用心してください。 そうしなければならないのであれば、文のタイムアウトを強制するのが賢明です。
SIMILAR TO
がPOSIX書式の正規表現と同じ多くの機能を提供するので、SIMILAR TO
パターンを使う検索は同様のセキュリティ問題を抱えています。
LIKE
検索は、他の2つの方法よりずっと単純ですので、悪意があるかもしれないパターンのソースで使うのにはより安全です。
LIKE
string
LIKEpattern
[ESCAPEescape-character
]string
NOT LIKEpattern
[ESCAPEescape-character
]
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つ書きます。
standard_conforming_stringsパラメータをoffにしている場合、リテラル文字列定数に記述するバックスラッシュを二重にする必要があります。 詳細は4.1.2.1を参照してください。
同時にESCAPE ''
と記述することでエスケープ文字を選択しないことも可能です。
これにより、事実上エスケープ機構が働かなくなります。つまり、パターン内のアンダースコアおよびパーセント記号の特別な意味を解除することはできなくなります。
現在のロケールに従って大文字小文字を区別しない一致を行うのであれば、LIKE
の代わりにILIKE
キーワードを使うことができます。
これは標準SQLではなく、PostgreSQLの拡張です。
~~
演算子はLIKE
式と等価で、~~*
はILIKE
に対応します。
またNOT LIKE
およびNOT ILIKE
を表す!~~
および!~~*
演算子があります。
これら全ての演算子はPostgreSQL固有のものです。
単に文字列の先頭からの開始が必要なだけのケースであれば、接頭辞演算子^@
とそれに対応するstarts_with
関数もあります。
SIMILAR TO
正規表現string
SIMILAR TOpattern
[ESCAPEescape-character
]string
NOT SIMILAR TOpattern
[ESCAPEescape-character
]
SIMILAR TO
演算子は、そのパターンが与えられた文字列に一致するかどうかにより、真もしくは偽を返します。
これは、標準SQLの正規表現定義を使用してパターンを解釈するという点以外は、LIKE
に類似しています。
SQLの正規表現は、LIKE
表記と一般的な正規表現の表記とを混ぜ合わせたようなものになっています。
LIKE
と同様、SIMILAR TO
演算子は、そのパターンが文字列全体に一致した場合のみ真を返します。これは、パターンが文字列の一部分であっても一致する、一般的な正規表現の動作とは異なっています。
また、LIKE
と同様、SIMILAR TO
では、%
および_
を、それぞれ任意の文字列および任意の単一文字を意味するワイルドカード文字として使用します(これらは、POSIX正規表現での.*
および.
に相当します)。
LIKE
から取り入れた上記の機能に加え、SIMILAR TO
では、以下のようにPOSIX正規表現から取り入れたパターンマッチメタ文字もサポートしています。
|
は、二者択一(2つの選択肢のうちいずれか)を意味します。
*
は、直前の項目の0回以上の繰り返しを意味します。
+
は、直前の項目の1回以上の繰り返しを意味します。
?
は、直前の項目の0回もしくは1回の繰り返しを意味します。
{
m
}
は、直前の項目の正確なm
回の繰り返しを意味します。
{
m
,}
は、直前の項目のm
回以上の繰り返しを意味します。
{
m
,
n
}
は、直前の項目のm
回以上かつn
回以下の繰り返しを意味します。
丸括弧()
は、項目を1つの論理項目にグループ化することができます。
大括弧式[...]
は、POSIX正規表現と同様に文字クラスを指定します。
SIMILAR TO
ではピリオド(.
)はメタ文字ではないことに注意してください。
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(
を使用して、SQL正規表現パターンに一致する部分文字列を取り出すことができます。
string
from pattern
for escape-character
)SIMILAR TO
と同様、指定したパターンがデータ文字列全体に一致する必要があります。一致しない場合、関数は終了し、NULLを返します。一致した場合に返されるべきパターンの一部を示すために、エスケープ文字の後に二重引用符("
)を繋げたものを2つパターンに含める必要があります。
これらの印で括られたパターンの一部に一致するテキストが返されます。
例:#"
を使用して返される文字列を区切ります。
substring('foobar' from '%#"o_b#"%' for '#') oob substring('foobar' from '#"o_b#"%' for '#') NULL
表 9.14に、POSIX正規表現を使ったパターンマッチに使用可能な演算子を列挙します。
表9.14 正規表現マッチ演算子
演算子 | 説明 | 例 |
---|---|---|
~ | 正規表現にマッチ、大文字小文字の区別あり | 'thomas' ~ '.*thomas.*' |
~* | 正規表現にマッチ、大文字小文字の区別なし | 'thomas' ~* '.*Thomas.*' |
!~ | 正規表現にマッチしない、大文字小文字の区別あり | 'thomas' !~ '.*Thomas.*' |
!~* | 正規表現にマッチしない、大文字小文字の区別なし | 'thomas' !~* '.*vadim.*' |
POSIX正規表現は、パターンマッチという意味合いでは、LIKE
およびSIMILAR TO
演算子よりもさらに強力です。
egrep
、sed
、あるいはawk
のような多くのUnixツールはここで解説しているのと類似したパターンマッチ言語を使用しています。
正規表現とは文字列の集合(正規集合)の簡略された定義である文字が連なっているものです。
ある文字列が正規表現で記述された正規集合の要素になっていれば、その文字列は正規表現にマッチしていると呼ばれます。
LIKE
と同様、正規表現言語で特殊文字とされているもの以外、パターン文字は文字列と完全にマッチされます。とは言っても、正規表現はLIKE
関数が使用するのとは異なる特殊文字を使用します。
LIKE
関数のパターンと違って正規表現は、明示的に正規表現が文字列の最初または最後からと位置指定されていない限り文字列内のどの位置でもマッチを行えます。
例:
'abc' ~ 'abc' true 'abc' ~ '^a' true 'abc' ~ '(b|d)' true 'abc' ~ '^(b|c)' false
POSIXパターン言語について以下により詳しく説明します。
2つのパラメータを持つsubstring
関数、substring(
を使用して、POSIX正規表現パターンにマッチする部分文字列を取り出すことができます。
この関数は、マッチするものがない場合にはNULLを返し、ある場合はパターンにマッチしたテキストの一部を返します。
しかし、丸括弧を持つパターンの場合、最初の丸括弧内部分正規表現(左丸括弧が最初に来るもの)にマッチするテキストの一部が返されます。
この例外を起こさずにパターン中に丸括弧を使用したいのであれば、常に正規表現全体を丸括弧で囲むことができます。
パターン内の抽出対象の部分文字列より前に丸括弧が必要な場合、後述の捕捉されない丸括弧を参照してください。
string
from pattern
)
例:
substring('foobar' from 'o.b') oob substring('foobar' from 'o(.)b') o
regexp_replace
関数は、POSIX正規表現パターンにマッチする部分文字列を新規テキストと置換します。
構文は、regexp_replace
(source
, pattern
, replacement
[, flags
])です。
pattern
にマッチしない場合は、source
文字列がそのまま返されます。
マッチすると、マッチ部分文字列をreplacement
文字列で置換したsource
文字列が返されます。
replacement
文字列に\
n
(n
は1から9までの数字)を入れて、パターン内のn
番目の丸括弧つき部分表現にマッチする元の部分文字列を挿入することができます。
また、\&
を入れて、パターン全体とマッチする部分文字列を挿入することもできます。
置換テキスト内にバックスラッシュそのものを挿入する必要がある時は\\
と記述します。
flags
パラメータは、関数の動作を変更するゼロもしくはそれ以上の1文字フラグを含むオプションのテキスト文字列です。フラグi
は大文字小文字を区別しないマッチを指定する一方、フラグg
は、最初にマッチしたもののみではなく、それぞれマッチした部分文字列の置換を指定します。
有効なフラグは(g
を除く)表 9.22に記述されています。
例:
regexp_replace('foobarbaz', 'b..', 'X') fooXbaz regexp_replace('foobarbaz', 'b..', 'X', 'g') fooXX regexp_replace('foobarbaz', 'b(..)', 'X\1Y', 'g') fooXarYXazY
regexp_match
関数はPOSIX正規表現パターンを文字列にマッチさせた結果、捕捉された最初の部分文字列のテキスト配列を返します。
regexp_match
(string
, pattern
[, flags
])の構文になります。
マッチするものがなければ、結果はNULL
となります。
マッチする部分があり、かつpattern
が丸括弧で括られた部分文字列を含まない場合、結果はパターン全体にマッチする部分文字列を含む単一要素のテキスト配列となります。
マッチする部分があり、かつpattern
が丸括弧で括られた部分文字列を含む場合、結果はテキスト配列で、そのn
番目の要素はpattern
のn
番目に丸括弧で括られた部分文字列にマッチする部分文字列となります(「捕捉されない」丸括弧は数えません。詳細は以下を参照してください)。
flags
パラメータは、関数の動作を変更するゼロもしくは複数の単一文字フラグを含むオプションのテキスト文字列です。
有効なフラグは表 9.22に記載されています。
例を示します。
SELECT regexp_match('foobarbequebaz', 'bar.*que'); regexp_match -------------- {barbeque} (1 row) SELECT regexp_match('foobarbequebaz', '(bar)(beque)'); regexp_match -------------- {bar,beque} (1 row)
マッチするときはマッチする部分文字列全体、マッチしないときはNULL
を返したいというよくあるケースは、以下のように書くことができます。
SELECT (regexp_match('foobarbequebaz', 'bar.*que'))[1]; regexp_match -------------- barbeque (1 row)
regexp_matches
関数はPOSIX正規表現パターンを文字列にマッチさせた結果、捕捉された部分文字列のテキスト配列の集合を返します。
構文はregexp_match
と同じです。
この関数は、マッチするものがないときは行を返しませんが、マッチするものがあり、g
フラグが指定されていないときは1行だけ、マッチするものがN
個あり、g
フラグが指定されているときはN
行を返します。
返される各行は上でregexp_match
について説明したのと全く同じで、マッチする部分文字列全体、または丸括弧で括られた部分文字列にマッチする部分文字列を含むテキスト配列です。
regexp_matches
は表 9.22に示すすべてのフラグに加え、最初のマッチだけでなくすべてのマッチを返すg
を受け付けます。
例を示します。
SELECT regexp_matches('foo', 'not there'); regexp_matches ---------------- (0 rows) SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g'); regexp_matches ---------------- {bar,beque} {bazil,barf} (2 rows)
最初にマッチするものだけが必要なときはregexp_match()
を使う方がより簡単で効率的ですから、regexp_matches()
はほとんどの場合g
フラグを指定して使われるでしょう。
しかし、regexp_match()
はPostgreSQLのバージョン10以上でのみ利用できます。
古いバージョンを使う時によくある手法は、以下の例のように、副SELECTの中にregexp_matches()
の呼び出しを入れることです。
SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab;
これはregexp_match()
と同じく、マッチするものがあればテキスト配列を生成し、マッチしなければNULL
となります。
副SELECTを使わなければ、マッチするものがないテーブル行については問い合わせの出力が生成されず、多くの場合に期待される動作と異なります。
regexp_split_to_table
関数はPOSIX正規表現パターンを区切り文字として使用し、文字列を分割します。regexp_split_to_table
(string
, pattern
[, flags
])の構文になります。
pattern
にマッチしない場合、関数はstring
を返します。
少なくともひとつのマッチがあれば、それぞれのマッチに対して関数は最後のマッチの終わり(あるいは文字列の始め)から最初のマッチまでのテキストを返します。
もはやマッチしなくなると最後のマッチの終わりから文字列の最後までテキストを返します。
flags
パラメータは、関数の動作を変更するゼロもしくは複数の単一文字フラグを含むオプションのテキスト文字列です。
regexp_split_to_table
は表 9.22で記載されているフラグをサポートします。
regexp_split_to_array
関数は、regexp_split_to_array
がその結果をtext
配列で返すことを除いて、regexp_split_to_table
と同じ動作をします。
regexp_split_to_array
(string
, pattern
[, flags
])の構文になります。
パラメータはregexp_split_to_table
のものと同じです。
例:
SELECT foo FROM regexp_split_to_table('the quick brown fox jumps over the lazy dog', '\s+') AS foo; foo ------- the quick brown fox jumps over the lazy dog (9 rows) SELECT regexp_split_to_array('the quick brown fox jumps over the lazy dog', '\s+'); regexp_split_to_array ----------------------------------------------- {the,quick,brown,fox,jumps,over,the,lazy,dog} (1 row) SELECT foo FROM regexp_split_to_table('the quick brown fox', '\s*') AS foo; foo ----- t h e q u i c k b r o w n f o x (16 rows)
最後の例が明らかにしているように、regexp分割関数は文字列の最初あるいは終わり、もしくは前のマッチの直後に発生する長さを持たないマッチを無視します。
regexp_match
およびregexp_matches
で実装されたregexpマッチの厳格な定義にこれは相容れませんが、実務上は最も使い勝手の良い動作です。
Perlのような他のソフトウェアシステムも似たような定義を使用します。
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は常に、まず正規表現はARE規則に従うと推測します。 しかし、REパターンの前に、9.7.3.4に記載されているような埋め込みオプションを追加することにより、より限られたERE、あるいはBRE規則を選択することができます。 これは、POSIX1003.2の規則を正確に期待しているアプリケーションとの互換性に関して有用です。
正規表現は|
で区切られた、1つまたは複数のブランチとして定義されます。
ブランチのいずれか1つにマッチすればマッチしたことになります。
ブランチはゼロ個以上の量化アトムもしくは制約の連結です。 最初のものにマッチに、次に第2番目のものにマッチを、というふうにマッチします。なお、空のブランチは空文字列にマッチします。
量化アトムとは、単一の量指定子が後ろに付くアトムのことです。 量指定子がないと、アトムにマッチするものがマッチしたことになります。 量指定子がある場合、アトムとのマッチが何回あるかでマッチしたことになります。 アトムは、表 9.15に示したもののいずれかを取ることができます。 表 9.16に設定可能な量指定子とその意味を示します。
制約は空文字に、特定の条件に合う場合のみにマッチします。 アトムを使用できるところには制約を使用することができます。ただしその後に量指定子を付けることはできません。 単純な制約を表 9.17に示します。後で他のいくつかの制約を説明します。
表9.15 正規表現のアトム
アトム | 説明 |
---|---|
( 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はバックスラッシュ\
を終端とすることはできません。
もしstandard_conforming_stringsパラメータをoffにしていた場合、リテラル文字列定数に記述するバックスラッシュは2倍必要となります。 詳細は4.1.2.1を参照してください。
表9.16 正規表現量指定子
量指定子 | マッチ |
---|---|
* | アトムの0個以上複数の並びにマッチ |
+ | アトムの1個以上複数の並びにマッチ |
? | アトムの0個または1個の並びにマッチ |
{ m } | アトムの正確にm 個の並びにマッチ |
{ m ,} | アトムのm 個以上の並びにマッチ |
{ m , n } | アトムのm 個以上n 以下の並びにマッチ。
m はn を超えることはできません。 |
*? | * の最短マッチを行うバージョン |
+? | + の最短マッチを行うバージョン |
?? | ? の最短マッチを行うバージョン |
{ m }? | { m } の最短マッチを行うバージョン |
{ m ,}? | { m ,} の最短マッチを行うバージョン |
{ m , n }? | { m , n } の最短マッチを行うバージョン |
{
...
}
を使用する形式はバウンドとして知られています。
バウンド内のm
とn
という数は符号なし10進整数であり、0以上255以下の値を取ることができます。
最短マッチを行う量指定子(AREのみで使用可能)は、対応する通常の(欲張りの)ものと同じものにマッチしますが、最大のマッチではなく最小のマッチを取ります。 詳細は9.7.3.5を参照してください。
量指定子の直後に量指定子を続けることはできません。例えば**
は無効です。
量指定子から式や副式を始めることはできず、また、^
や|
の直後に付けることもできません。
表9.17 正規表現制約
制約 | 説明 |
---|---|
^ | 文字列の先頭にマッチ |
$ | 文字列の末尾にマッチ |
(?= re ) | 先行肯定検索は、re にマッチする部分文字列が始まる任意の場所にマッチします(AREのみ)。 |
(?! re ) | 先行否定検索は、re にマッチしない部分文字列が始まる任意の場所にマッチします(AREのみ)。 |
(?<= re ) | 後方肯定検索はre にマッチする部分文字列が終わる任意の場所にマッチします(AREのみ)。 |
(?<! re ) | 後方否定検索re にマッチしない部分文字列が終わる任意の場所にマッチします(AREのみ)。 |
先行検索制約および後方検索制約には後方参照(9.7.3.3を参照)を含めることはできません。また、その中の括弧は全て取り込むものではないとみなされます。
ブラケット式とは、[]
内の文字のリストです。
通常これはそのリスト内の任意の1文字にマッチします(しかし、以降を参照してください)。
リストが^
から始まる場合、そのリストの残りにはない任意の1文字にマッチします。
リスト内の2文字が-
で区切られていた場合、これは2つ(を含む)の間にある文字範囲全体を表す省略形となります。例えば、ASCIIにおける[0-9]
は全ての数字にマッチします。
例えばa-c-e
といった、終端を共有する2つの範囲は不正です。
範囲は並びの照合順に非常に依存しています。ですので、移植予定のプログラムではこれに依存してはなりません。
このリストに]
そのものを含めるには、それを先頭文字(もしそれが使用されれば^
の後)にしてください。
-
そのものを含めるには、それを先頭もしくは末尾の文字とするか、範囲の2番目の終端としてください。
-
を範囲の最初の終端で使用するには、[.
と.]
でそれを囲み、照合要素(後述)にしてください。
これら文字と、[
(次段落を参照)のなんらかの組み合わせ、およびエスケープ(AREのみ)を例外として、他の全ての特殊文字はブラケット式内では特殊な意味を持ちません。
特に、\
はEREとBRE規則に従う場合は特別でなくなります。しかし、AREでは(エスケープの始まりとして)特別な意味を持ちます。
ブラケット式内に、照合要素(文字、単一文字であるかのように照合する複数文字の並び、もしくはそれぞれの照合並びの名前)が[.
と.]
の間にあると、その照合要素の文字の並びを意味します。
この並びはブラケット式のリストの一要素として取り扱われます。
このことにより、ブラケット式は要素を照合する複数文字を含むブラケット式を1文字以上にマッチさせることができます。例えば、照合並びがch
照合要素を含む場合、正規表現[[.ch.]]*c
はchchcc
という文字の最初の5文字にマッチします。
今のところ、PostgreSQLは複数文字照合要素をサポートしません。 この情報は将来の振舞いの可能性を説明したものです。
ブラケット式内の[=
と=]
の間に照合要素は同値クラスです。全ての照合要素の文字の並びが自身を含むものと等価であることを示します。
(他に等価な照合要素がある場合、[.
と.]
で囲まれたかのように扱われます。)
例えば、[[=o=]]
、[[=^=]]
および[o^]
が全て同意語であれば、o
と^
は同値クラスのメンバです。
同値クラスは範囲の終端にはなりません。
ブラケット式内では、[:
と:]
の間にある文字クラスの名称は、そのクラスに属する全ての文字のリストを意味します。
標準文字クラス名は、alnum
、alpha
、blank
、cntrl
、digit
、graph
、lower
、print
、punct
、space
、upper
、xdigit
です。
これらはctypeで定義された文字クラスを意味します。
ロケールは別のものを提供可能です。
文字クラスは範囲の終端では使用することができません。
ブラケット式には2つの特殊な場合があります。[[:<:]]
と[[:>:]]
というブラケット式は、先頭と終端の単語がそれぞれ空文字であることにマッチする制約です。
単語は、単語文字が前後に付かない単語文字の並びとして定義されます。
単語文字とは(ctypeで定義されている)1つのalnum
文字またはアンダースコアです。
これは、POSIX 1003.2との互換性はありますが、そこでは定義されていない式です。ですので、他システムへ移植予定のソフトウェアでの使用には注意が必要です。
通常後述の制約エスケープの方がよく使われます。これはもはや標準ではありませんが、入力しやすいものです。
エスケープとは、\
から始まり英数字がその後に続く特殊な並びです。
エスケープには、文字エントリ、クラス省略、制約エスケープ、後方参照といった様々な変種があります。
\
の後に英数字が続くけれども、有効なエスケープを構成しない並びはAREでは不正です。
EREにはエスケープはありません。ブラケット式の外側では、\
の後に英数字が続く並びは単に普通の文字としてその文字を意味します。ブラケット式の内側では、\
は普通の文字です。
(後者はEREとARE間の非互換性の1つです。)
文字エントリエスケープは非印字文字やRE内でその他の不便な文字の指定を簡略化するために存在します。 これらを表 9.18に示します。
クラス省略エスケープは、あるよく使用される文字クラスの省略形を提供します。 これらを表 9.19に示します。
制約エスケープは、指定した条件に合う場合に空文字にマッチする制約をエスケープとして表したものです。 これらを表 9.20に示します。
後方参照(\
n
)は、直前に括弧で囲まれた副式によってマッチされた、n
番目の同一文字列にマッチします(表 9.21を参照してください)。
例えば、([bc])\1
はbb
もしくはcc
にマッチしますが、bc
やcb
にはマッチしません。REでは副式全体は後方参照の前になければなりません。
副式は開括弧の順番で番号付けされます。
取り込まない括弧は副式を定義しません。
表9.18 正規表現文字エントリエスケープ
エスケープ | 説明 |
---|---|
\a | C言語と同じ警報(ベル)文字 |
\b | C言語と同じバックスペース |
\B | バックスラッシュの必要な二重化回数を減らすためのバックスラッシュ(\ )の同義語 |
\c X | (ここでX は任意の文字で)その下位5ビットがX と同一、その他のビットが0となる文字 |
\e | 照合順名がESC となる文字、それに失敗したら、033 という8進数値を持つ文字。 |
\f | C言語と同じ改ページ |
\n | C言語と同じ改行 |
\r | C言語と同じ復帰 |
\t | C言語と同じ水平タブ |
\u wxyz | (ここでwxyz は正確に4桁の16進数で)その16進数での値が0x wxyz という文字
|
\U stuvwxyz | (ここでstuvwxyz は正確に8桁の16進数で)その16進数での値が0x stuvwxyz という文字
|
\v | C言語と同じ垂直タブ |
\x hhh | (ここでhhh は任意の16進数の並びで)その文字の16進数値が0x hhh となる文字(使用される16進数の桁数にかかわらず単一の文字)
|
\0 | その値が0 (NULLバイト)となる文字 |
\ xy | (ここでxy は正確に2桁の8進数で、後方参照ではない)その値が0 xy となる文字 |
\ xyz | (ここでxyz は正確に3桁の8進数で、後方参照ではない)その値が0 xyz となる文字 |
16進数の桁とは0
-9
、a
-f
、A
-F
です。
8進数の桁とは0
-7
です。
ASCIIの範囲(0-127)外の値を指定した数字のエントリエスケープは、その意味がデータベースエンコーディングに依存します。
エンコーディングがUTF-8の場合、エスケープ値はユニコード符号位置に相当します。例えば、\u1234
は文字U+1234
を意味します。
その他のマルチバイトエンコーディングでは、文字エントリエスケープはたいてい文字のバイト値の連結を指定します。
エスケープ値がデータベースエンコーディングでのいかなる正当な文字にも対応しない場合、エラーは起こりませんが、いかなるデータにもマッチしません。
この文字エントリエスケープは常に普通の文字と解釈されます。
例えば、\135
はASCIIの]
となり、\135
はブラケット式の終端にはなりません。
表9.19 正規表現クラス省略エスケープ
エスケープ | 説明 |
---|---|
\d | [[:digit:]] |
\s | [[:space:]] |
\w | [[:alnum:]_]
(アンダースコアが含まれることに注意) |
\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.20 正規表現制約エスケープ
単語は前述の[[:<:]]
と[[:>:]]
の規定通りに定義されます。ブラケット式内では制約エスケープは不正です。
表9.21 正規表現後方参照
エスケープ | 説明 |
---|---|
\ m | (ここでm は非ゼロの数です。)副式のm 番目への後方参照 |
\ mnn | (ここでm は非ゼロの数です。nn でさらに桁を指定します。mnn 10進数値は取り込み括弧の数よりも多くてはなりません。)副式のmnn 番目への後方参照 |
8進数の文字エントリエスケープと後方参照の間には曖昧性があります。上でヒントとして示したようにこれは以下の発見的手法で解決されます。 先頭の0は常に8進数エスケープを示します。 その後に数字が続かない単一の非ゼロ数字は常に後方参照として解釈されます。 ゼロから始まらない複数数字の並びは、適切な副式の後にあれば(つまり、その番号が後方参照用の範囲内にあれば)後方参照として解釈されます。さもなくば、8進数として解釈されます。
上述の主構文の他に、特殊な形式や雑多な構文的な機能が使用可能です。
REは、2つの特殊な決定子前置詞のどちらかから始まります。
REが***:
から始まるものであれば、REの残りはAREと解釈されます。
(PostgreSQLはREをAREとして推測するため、通常は影響を受けません。ただし、正規表現関数に対してflags
パラメータを指定されたEREやBREモードでは影響を受けます。)
REが***=
から始まるものであれば、REの残りは、全ての文字を普通の文字とみなしたリテラル文字列と解釈されます。
AREは埋め込みオプションから始められます。(?
xyz
)
という並びで残りのREに影響するオプションを指定します(ここでxyz
は1つ以上の英字です)。
このオプションは、事前に決定されたオプションを上書きします。— 特に、正規表現演算子、もしくは正規表現関数に与えられたflags
パラメータにより示される大文字小文字の区別を上書きします。
使用可能なオプション文字を表 9.22に示します。
これらの同じオプション文字が、正規表現関数のflags
パラメータで使用されることに注意して下さい。
表9.22 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ではなくリテラルとして扱われる場合、これらのメタ構文拡張は使用できません。
REが文字列の中の1つ以上の部分文字列とマッチする場合において、REは最初にマッチが始まった部分文字列とマッチします。 その位置からまた1つ以上の部分文字列とマッチした際は、正規表現は最短マッチを行わない(欲張り型)か最短マッチを行う(非欲張り型)かによって、最長マッチもしくは最短マッチの文字列のどちらかにマッチします
REが最長マッチかどうかは以下の規則によって決まります。
ほとんどのアトムおよび全ての式は欲張り属性を持ちません(これらは変動する量のテキストにまったくマッチしないからです)。
REを括弧で括ることは欲張りかどうかを変更しません。
{
m
}
もしくは{
m
}?
といった固定繰り返し数の量指定子を持つ量指定付きアトムは、アトム自身と同一の欲張りさを持ちます(まったく持たない可能性もあります)。
他の通常の量指定子({
m
,
n
}
、m
とn
が等しい場合も含みます)を持つ量指定付きアトムは欲張り型です(最長マッチを使用します)。
他の非欲張り型量指定子({
m
,
n
}?
、m
とn
が等しい場合も含みます)を持つ量指定付きアトムは非欲張り型です(最短マッチを使用します)。
最上位レベルの|
演算子を持たない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全体に使用して、それぞれ、欲張りか欲張りでないかを強制することが可能です。
RE全体に対してはその要素から推論されるものと異なる欲張りさの属性が必要な場合に、これは便利です。
例として、数字をいくつか含む文字列を数字とその前後の部分に分けようとしているとします。
次のようにしてみるかもしれません。
SELECT regexp_match('abc01234xyz', '(.*)(\d+)(.*)');
Result: {abc0123,4,xyz}
上手くいきませんでした。最初の.*
が欲張りで、可能なだけ「消費」してしまい、\d+
は最後の可能な場所で最後の数字にマッチします。
欲張りでなくすることで直そうとするかもしれません。
SELECT regexp_match('abc01234xyz', '(.*?)(\d+)(.*)');
Result: {abc,0,""}
またもや上手くいきませんでした。今度は、REが全体として欲張りでなくなってしまい、できる限り早く全体に渡るマッチを終わらせてしまうからです。 RE全体として欲張りにすることで欲しいものが得られます。
SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
Result: {abc,01234,xyz}
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
は、継続して、文字列の先頭と末尾のみにマッチします。
部分的に改行を区別するマッチが指定されると、.
とブラケット式は改行を区別するマッチを行うようになりますが、^
と$
は変更されません。
部分的に改行を区別する逆マッチが指定されると、^
と$
は改行を区別するマッチを行うようになりますが、.
とブラケット式は変更されません。
これはあまり有用ではありません。対称性のために提供されています。
本実装では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では、\
は[]
内でも特別な文字です。したがって、ブラケット式では\
を\\
と記述しなければなりません。
BREはEREといくつかの面において異なります。
BREにおいては、|
、+
、?
は普通の文字であり、それらの機能と等価なものはありません。
バウンドの区切りは\{
と\}
であり、{
と}
自身は普通の文字です。
副式を入れ子にするための括弧は\(
と\)
であり、(
と)
自身は普通の文字です。
^
は、REの先頭にある場合や括弧内の副式の先頭の場合を除き、普通の文字です。
$
は、REの末尾にある場合や括弧内の副式の末尾の場合を除き、普通の文字です。
また、*
はREの先頭にある場合や括弧内の副式の先頭にある場合には普通の文字になります(その前に^
が付いている可能性もあります)。
最後に、1桁の後方参照を使用することができ、また、BREにおいては、\<
と\>
はそれぞれ[[:<:]]
と[[:>:]]
と同義です。