式
REFind 関数および REFindNoCase 関数は、検索文字列内にある、正規表現と最初に一致した文字列の位置を返します。次の例の検索文字列には、正規表現に一致する文字列が 2 つありますが、最初の文字列のインデックスのみが返されます。
<! --- IndexOfOccurrence の値は 5 です。--->
正規表現に一致する箇所をすべて検索するには、REFind 関数および REFindNoCase 関数を複数回呼び出す必要があります。
REFind 関数および REFindNoCase 関数には、オプションの第 3 パラメータがあり、検索文字列のどのインデックスから検索を開始するかを指定できます。デフォルトでは、開始位置のインデックスは 1(文字列の先頭)です。
この例で、正規表現の 2 番目の一致箇所を検索するには、開始インデックスを 8 に指定して REFind を呼び出します。
<! --- IndexOfOccurrence の値は 9 です。--->
この場合は、2 つ目の " BIG " の開始インデックスであるインデックス 9 が返されます。
2 つ目の文字列を検索するためには、最初の文字列がインデックス 5 にあり、長さが 5 であるという情報が必要です。しかし、REFind では、文字列の開始インデックスは返されますが、長さは返されません。したがって、2 回目の REFind を実行するためには、一致した文字列の長さを調べるか、または正規表現でサブ式を使用する必要があります。
REFind 関数および REFindNoCase 関数では、一致したサブ式に関する情報を取得できます。これらの関数の第 4 パラメーターである ReturnSubExpression を True に設定すると、pos と len の 2 つの配列を持つ CFML 構造体が返されます。この構造体には、正規表現のサブ式に一致したテキスト文字列の位置と長さが含まれています。次に例を示します。
<cfoutput> <cfdump var="#sLenPos#"> </cfoutput><br>
pos 配列の要素 1 には、正規表現に一致した文字列の、検索文字列における開始インデックスが含まれています。len 配列の要素 1 には、一致した文字列の長さが含まれています。この例では、最初の "BIG" 文字列のインデックスは 5 であり、長さも 5 です。正規表現に一致する文字列が存在しない場合、pos 配列と len 配列は、値が 0 の要素を 1 つ含みます。
返された情報は、mid などの他の文字列関数で使用できます。次の例は、検索文字列内の正規表現に一致する文字列を返します。
<cfset sLenPos=REFind(" BIG ", myString, 1, "True")> <cfoutput> #mid(myString, sLenPos.pos[1], sLenPos.len[1])# </cfoutput>
pos 配列の 2 番目以降の各要素には、各サブ式に最初に一致した検索文字列内の文字列の位置が含まれます。len 配列の 2 番目以降の各要素には、各サブ式に一致した文字列の長さが含まれます。
前述の例では、正規表現 " BIG " にはサブ式が含まれていません。したがって、REFind 関数によって返される構造体の各配列の要素は 1 つです。
前述の例を実行した後、REFind をもう一度呼び出して、正規表現の次の一致箇所を検索できます。2 回目の呼び出しでは、最初の呼び出しで得た情報を使用します。
<! --- subtract 1 because you need to start at the first space ---> <cfset sLenPos2=REFind(" BIG ", "Some BIG BIG string", newstart, "True")> <cfoutput> <cfdump var="#sLenPos2#"> </cfoutput><br>
正規表現にサブ式が含まれている場合は、pos と len の要素 1 の後の各要素で、各サブ式に一致する検索文字列内の最初の文字列の位置と長さが示されます。
次の例で、式 [A-Za-z]+ は、正規表現のサブ式です。式 ([A-Za-z])[ ] によって、"is is" が最初に一致します。
"There is is a cat in in the kitchen", 1, "True")> <cfoutput> <cfdump var="#sLenPos#"> </cfoutput><br>
sLenPos.pos[1] と sLenPos.len[1] には、正規表現全体の一致に関する情報が含まれています。配列要素 sLenPos.pos2 と sLenPos.len2 には、最初のサブ式("is")に関する情報が含まれています。REFind では、正規表現の最初の一致に関する情報のみが返されるので、sLenPos 構造体には、2 番目の一致である "in in" に関する情報は含まれません。
次の例の正規表現では、2 つのサブ式を使用しています。したがって、返される構造体の各配列には、正規表現全体に最初に一致した文字列、最初のサブ式に最初に一致した文字列、および 2 番目のサブ式に最初に一致した文字列の、位置と長さが含まれます。
<cfset regex = "(apples) and (pears)"> <cfset sLenPos = REFind(regex, sString, 1, "True")> <cfoutput> <cfdump var="#sLenPos#"> </cfoutput>
サブ式の使用方法の詳細については、『CFML リファレンス』の ColdFusion 関数に関する章の REFind および REFindNoCase の節を参照してください。
最短一致の指定
正規表現の修飾子である ?、*、+、{min,} および {min,max} では、式の繰り返し回数の最小、最大、またはその両方が指定されます。デフォルトでは、正規表現に一致する最長の文字列が検索文字列の中から検索されます。この動作を最長一致と呼びます。
例えば、正規表現 "<b>(\.*)</b>" を使用して文字列 "<b>one</b> <b>two</b>" を検索するとします。正規表現 "<b>(\.*)</b>" は、次の両方に一致します。
- <b>one</b>
- <b>one</b> <b>two</b>
デフォルトでは、正規表現に一致する最長の文字列が検索文字列の中から検索されます。次のコードは、この例の結果を示します。
<cfset sLenPos=REFind("<b>(.*)</b>", "<b>one</b> <b>two</b>", 1, "True")> <cfoutput> <cfdump var="#sLenPos#"> </cfoutput><br>
このように、文字列の開始位置は 1 でその長さは 21 です。これは、2 つの一致候補のうちの長いほうに対応します。
しかし、このデフォルトの動作を無効にして、正規表現に一致する最短の文字列を検索することもできます。ColdFusion には、最短の文字列に一致するように指定する、最短一致修飾子が用意されています。次の表で、これらの式について説明します。
|
説明 |
---|---|
*? |
* の最短一致バージョン |
+? |
+ の最短一致バージョン |
?? |
? の最短一致バージョン |
{min,}? |
{min,} の最短一致バージョン |
{min,max}? |
{min,max} の最短一致バージョン |
{n}? |
{n} と同じです。表記上の |
前の例に変更を加えて、最短一致のシンタックスを使用すると、次のようなコードになります。
<cfset sLenPos=REFind("<b>(.*?)</b>", "<b>one</b> <b>two</b>", 1, "True")> <cfoutput> <cfdump var="#sLenPos#"> </cfoutput><br>
このように、正規表現で検索された文字列の長さは 10 です。これは文字列 "<b>one</b>" に対応します。