HmJre.dllにおける正規表現(Ver5.00対応版)
 HmJre.dllでは、山田和夫氏作のJRE32.DLLをベースに少しだけ正規表現を拡張しています。

 拡張したのは以下の形式です。
パターンの繰り返し回数指定
{n} 繰り返し指定その1(回数固定)
{n,} 繰り返し指定その2(n回以上)
{n,m} 繰り返し指定その3(n回以上、m回以下)


後方一致指定(V1.50にて一部拡張)
(?=expression)


後方不一致指定(V1.50にて一部拡張)
(?!expression)


前方一致指定
(?<=expression)


前方不一致指定
(?<!expression)


繰り返しマッチングでのものぐさ指定
*?
+?
??
{n,m}?
{n}?
{n,}?


一般的正規表現互換のタグ付き正規表現(V1.50から、\gはV4.13から)
\1 \2 ...、\g{数字}、\g{-数字}


ヒットした扱いにするタグ指定(HmJre.dll独自形式)
(?\tag-number)


ユニコード文字による指定(HmJre.dll独自形式、V1.95から)
[\uXXXX]


サロゲートペアとなるユニコード文字の指定(HmJre.dll独自形式、V3.38から、V4.11改版)
[\u{XXXX}]
[\UXXXXXXXX]


Perl互換の各種指定 (V3.00から)
\s (半角空白/タブ/改行にマッチ)
\S (半角空白/タブ/改行以外にマッチ)
\d (数字にマッチ、[0-9]と同じ)
\D (数字以外にマッチ、[^0-9]と同じ)
\c (英数字にマッチ、[a-zA-Z0-9_]と同じ)
\C (英数字以外にマッチ、[^a-zA-Z0-9_]と同じ)
\i (英字にマッチ、[a-zA-Z_]と同じ)
\I (英字以外にマッチ、[^a-zA-Z_]と同じ)
\y (単語の区切りにマッチ)
\Y (単語の区切りじゃない所にマッチ)


タグ指定出来ない括弧 (V3.00から)
(?:expression)


メタ文字を文字と見なす (V3.02から)
\Q...\E


コメント (V3.00から)
(?#expression)


繰り返し指定その1(固定回数)
 特定の正規表現パターンをn回繰り返す場合には、{n}を使います。nの部分には数値が入ります。例えばabcを3回繰り返すには、(abc){3}と記述します。
 数字を5回繰り返すには、[0-9]{5}と書きます。


繰り返し指定その2(n回以上)
 特定の正規表現パターンがn回以上出てくることにマッチさせるには、{n,}を使います。nの部分には数値が入ります。例えばabcが3回以上繰り返すには、(abc){3,}と記述します。


繰り返し指定その3(n回以上、m回以下)
 特定の正規表現パターンがn回以上m回以下出てくることにマッチさせるには、{n,m}を使います。nおよびmの部分には数値が入ります。


後方一致指定
 特定の正規表現パターンの後に、さらに特定の正規表現パターンが続くことを指定しつつ、正規表現にヒットする文字列としては前方部分のみとするような指定が出来ます。
 例えば、「abcxyz」という文字列を検索しつつ、ヒットする文字としては「abc」だけにしたいようなケースに使います。強調表示や置換の時に使うと便利です。
 例えば「abc」の後に「xyz」が続きつつ、ヒットする文字列は「abc」だけにしたい場合は、
abc(?=xyz)
 と指定します。
 後方一致指定の後ろにさらにパターンを指定すると、両方のAND指定という意味になります。例えば、
abc(?=[a-z])([x-z])
 と指定すると、a-zでなおかつx-zにマッチする文字列にヒットします。このような表記とタグ付き正規表見を組み合わせるといろいろ応用範囲が広がります。


後方不一致指定
 後方一致指定とは反対に、後方部分が特定のパターンにヒットしないことを必要とします。例えば「abc」の後ろが「xyz」でない場合に「abc」のみにヒットさせたいようなケースで使います。
 上記例では、
abc(?!xyz)
 と指定します。
 後方不一致指定の後ろにさらにパターンを指定すると、両方のAND指定という意味になります。例えば、
([a-z])((?!\1)[a-z])\2
 というパターンを使うことにより、「1文字目と2文字目は一致しなけども2文字目と3文字が一致する3文字の英単語」を検索することが出来ます。


前方一致指定
 特定の正規表現パターンの前に、さらに特定の正規表現パターンが存在していることを指定しつつ、正規表現にヒットする文字列としては後方部分のみとするような指定が出来ます。
 例えば、「abcxyz」という文字列を検索しつつ、ヒットする文字としては「xyz」だけにしたいようなケースに使います。強調表示や置換の時に使うと便利です。
 例えば「abc」の後に「xyz」が続きつつ、ヒットする文字列は「xyz」だけにしたい場合は、
(?<=abc)xyz
 と指定します。
 前方一致指定は、正規表現文字列の先頭以外の場合に書く場合で中に繰り返しパターンを書くことが出来ない等の制限があったのですが、Version 4.08からその制限を撤廃しました。ただし、「先頭じゃない」+「繰り返し指定あり」だと極端に遅くなる場合が多いので、ご注意ください。
 前方一致/不一致指定の中には改行文字を含むことが出来ない制限も以前はありましたが、Version 4.12(秀丸エディタのVersion 8.56に付属)からはその制限も無くなりました。

検索系コマンドでの次候補/下候補系コマンド実行時の注意:
 Version 3.xx以下のHmJre.dllでは、例えば「abcxyz」の「b」にカーソルがある状態で「(?<=abc)xyz」を検索してもヒットしないといった制限、つまり、前方一致指定のパターンが検索開始位置よりも前にヒットさせることが出来ない制限がありました。これについてはV4.00以降から廃止されて、うまくヒットするようになりました。ただし、秀丸エディタの強調表示の中ではこれ(検索開始位置のバックトラック)が効かないようにあえてやってるので、場合によっては期待した動作にならないことがありえます。(速度的な問題であえてそうしてます)


前方不一致指定
 前方一致指定とは反対に、前方部分が特定のパターンにヒットしないことを必要とします。例えば「xyz」の前が「abc」でない場合に「xyz」のみにヒットさせたいようなケースで使います。
 上記例では、
(?<!abc)xyz
 と指定します。
 前方不一致指定も前方一致指定と同様に、先頭以外の場所に書く場合は中身に繰り返しパターンを入れることが出来ない制限がありましたが、Version 4.08よりその制限を撤廃しました。ただし、「先頭じゃない」+「繰り返し指定あり」だと極端に遅くなる場合が多いので、ご注意ください。
 前方一致/不一致指定の中には改行文字を含むことが出来ない制限も以前はありましたが、Version 4.12(秀丸エディタのVersion 8.56に付属)からはその制限も無くなりました。

検索系コマンドでの次候補/下候補系コマンド実行時の注意:
 前方一致と同様に、HmJre.dllのVersion 3.xx以下では前方不一致指定した文字列が検索開始位置よりも前にマッチングさせられない制限がありました。これについてもVersion 4.00から撤廃されて、正しくヒットするようになりました。
 例えば上の例で、「abcxyz」の「x」の部分から検索を開始すると、Version 3.xx以下だとヒットしてましたが、Version 4.00からはヒットしなくなりました。


繰り返しマッチングでのものぐさ(non-greedy)指定
 「*」、「+」、「?」、「{n,m}」のような繰り返し指定は、原則として、もっとも長い文字列にマッチさせるように動作します。例えば「a*」の指定が"a"の文字が連続している文字列にヒットするとき、"a"の全体にヒットします。
 ものぐさ指定をした場合は、逆に、もっとも短い文字列にヒットしようとします。例えば「a*?」だけ指定すると、それは0文字にヒットします。

 例えば、「<」で始まって「>」で終わる文字列にヒットさせるために、「<.*>」と正規表現指定すると、それはそれで正しくヒットしますが、それだと「<AAA>CCC<BBB>」のような文字列の全体にヒットしてしまって都合が悪いです。そういう時に、ものぐさ指定して、例えば「<.*?>」のように指定すると、<AAA>の部分と<BBB>の部分の2つに分けてヒットして、とても便利です。

 また、正規表現のマッチング処理自体も、ものぐさ指定した方が動作速度が速くなる可能性が高いです。

ものぐさ指定とそうでない指定の優先順位:
 ものぐさ指定とそうでない指定を入れ子で指定した場合、基本的には外側の指定が優先されます。例えば「(a+?)+」のような指定をすると、それは「a+」と同じように、一番長い文字列にヒットします。逆に「(a+)+?」は「a+?」と同じ結果になります。{n}、{n,m}、{n,}のような繰り返し指定でも同じ法則が適用されるので、例えば「(a+?,){2}」は「+?」の指定が無視されて最大長さの文字列にヒットしますが、「(a+?,)(a+?,)」は最小長さの文字列にヒットします。ちなみに他の正規表現ライブラリは必ずしも「最大長さにヒットする」という法則じゃないらしくて、結果が違うケースがあるそうです。



一般的正規表現互換のタグ付き正規表現
 秀丸に従来から備わっているタグ付き正規表現は、"\f"という記号で検索パターンを区切ります。Perl等でのタグ付き正規表現では、カッコを使ってターゲットを指定する形になっています。そのPerl等と同じ方式のタグ指定が、HmJre.dllでも出来ます。こっちの方式でタグ指定する場合は、その指定されたタグを検索パターンの中に入れることも出来ます。
 こちらのやり方としては、タグ指定したい部分をカッコで囲みます。例えば、英数字と数字の組み合わせを検索しつつ、そのヒットした部分の数字の部分だけをタグ指定したい場合は、その数字に相当する部分をカッコで囲みます。
[a-z]+([0-9]+)
 のように指定します。そして、タグとしては、\1というのが数字の部分に相当することになります。または、
([a-z]+)([0-9]+)
 のようなパターンを指定した場合は、英字の部分が\1になり、数字の部分が\2となります。

 タグの対象となるのはあくまで一番ネストの浅いカッコだけなので、例えば、
(aaa|(bbb|ccc))
 と指定した場合には、それ全体が\1に相当し、\2、\3に該当する物は存在しないことになります。

 「\1」等を検索文字列の中に入れることも出来ます。例えば、
\<([a-z])((?!\1)[a-z])\2\>
 と指定すると、"see"や"all"のような、1文字目と2文字目は一致しないけども2文字目と3文字目が一致する3文字の単語を検索することが出来ます。

 HmJre.dllのVersion 4.13と秀丸エディタのVersion 8.58以降を組み合わせる場合には、タグの番号として15番までが指定できるようになりました。「\1〜\9」では9番までしか指定できないので、それとは別に、Perlと同じく「\g{数字}」および「\g{-数字}」の方式を採用しました。例えば
\g{10}
\g{-1}
 のような指定をします。例えば
(a+)(b+)(c+)(d+)(e+)(f+)(g+)(h+)(i+)(j+)
の (j+) 部分は、 \g{10} と表現して、置換が実行できます。
検索文字列の中で\gを使う場合、中の番号に負の数を指定すると、相対位置でタグを指定することが出来ます。例えば\g{-1}は、1つ前の括弧を対象とします。
(a+)(b+)\g{-2}
 の「\g{-2}」部分は(a+)部分に相当します。
補足:
 前方一致/不一致、後方一致/不一致指定についてはタグ付き正規表現でのカッコの対象外となります。例えば、"(aaa)(?!bbb)(ccc)"というパターンを指定した場合での"\2"に該当する部分は(ccc)部分となります。

 Perlでは、括弧が入れ子になった場合、入れ子になってる中の括弧についてもタグの指定が可能です。HmJre.dllではあくまで一番外側の括弧だけがタグの対象になります。入れ子になってる中の括弧をタグの対象にするには、外側の括弧を(?:....)にしてやる必要があります。その点互換性が無いのでご注意ください。


ヒットした扱いにするタグ指定(HmJre.dll独自形式)
 (?\tag-number)の形式を使うことで、検索でヒットした扱いにする部分を、検索パターン中のタグの指定で行うことが出来ます。前方一致/前方不一致指定などを使ってもいいんですけど、それとは別にこういうのも対応しました。

 例えば、aaabbbcccという文字列を検索しつつも、ヒットした扱いにしたいのがbbbだとすると、
(?\2)(aaa)(bbb)(ccc)
 と指定すればいいです。(?\tag-number)の指定は正規表現パターンのどこに入れてもかまいません。複数指定した場合は一番最後に指定した方のみが有効となります。

制限事項1
 複数行にマッチするような正規表現パターンについて、(?\tag-number)の指定で2行目以降にマッチする文字列を限定するような指定をすると、秀丸エディタの検索上は、その文字列にはマッチしない扱いになってしまいます。これは秀丸エディタの検索処理の制限上、仕方がないということになってます。

制限事項2
 例えば(a)|(b)(?\2)のような指定をすると、それが"a"にヒットした場合に「\2」に相当するものが存在しなくなってしまいます。この場合は「\2」の指定は無視されて、"a"全体にヒットした扱いになります。


ユニコード文字による指定(HmJre.dll独自形式、V1.95から)
 [...]または[^...]の中に限り、「\uXXXX」のような形で16進数のコードを使ってユニコードの文字を指定することが出来ます。
 [...]または[^...]の中での文字コード範囲指定の時に「\uXXXX」のような指定を使うと、文字コードの範囲をユニコードで指定したという意味になります。例えば「[\u4E00-\uFA2D]」と指定すると、ユニコード文字での4E00〜FA2Dにヒットする意味になり、結果として日本語/中国語のすべての漢字にヒットするような表現が可能になります。
 「\uXXXX」は、[...]および[^...]の外では使えません。


サロゲートペアとなるユニコード文字の指定(HmJre.dll独自形式、V3.38から)
 [...]または[^...]の中に限り、「\uXXXX」のような形で16進数のコードを使ってユニコードの文字を指定することが出来ますが、\uXXXXで表現出来るのは4桁に限ります。なので、16進数で4桁を超えるユニコード文字(いわゆるサロゲートペアの文字)は、この方法では指定することが出来ません。
 HmJre.dllのV3.38から、
\u{XXXXX}
のような形で任意桁数のユニコード文字を指定出来るようになりました。例えばユニコード16進数で25055の文字は、「\u{25055}」のように書くことが出来ます。

 \u{XXXXX}のような表記方法とは別に、サロゲートペアでの文字コードをそのまま「\uXXXX\uXXXX」と書いても同じ意味と解釈出来るようにもなりました。例えば\u{25055}の文字はサロゲートペアで表現すると「\uD854\uDC55」となります。

 Version 4.11からさらに、
「\Uxxxxxxxx]
 のように、大文字の'U'と8桁の16進数でも文字コード指定できるようになりました。例えば0x20E95のユニコード文字を指定するなら、
「\U00020E95]
 のように指定できるようになりました。
 ちなみに\uまたは\Uによるユニコード文字の指定が間違っていてもエラーにならず、適当に解釈されます。その点ご注意ください。


Perl互換の各種指定 (V3.00から)
 \s は、半角空白およびタブおよび改行文字(\n)にヒットします。[ \t\r\n]と書くのと同じです。
 \S は、逆に、半角空白/タブ/改行以外にヒットします。[^ \t\r\n]と書くのと同じです。
 \d は、数字にヒットします。[0-9]と同じです。
 \D は、数字以外にヒットします。[^0-9]と同じです。
 \c は、英数字と「_」にヒットします。[a-zA-Z0-9_]と同じです。Perlでは「\w」と書きますが、HmJre.dllでは、JRE32.DLLですでに\wが別の意味で使われている関係で、\cとなっています。その辺ご注意お願いします。
 \C は、英数字と「_」以外にヒットします。[^a-zA-Z0-9_]と同じです。Perlでの「\W」と同じですが、HmJre.dllでは「\C」となっているので注意が必要です。
 \i は、英字と「_」にヒットします。[a-zA-Z_]と同じです。
 \I は、英字と「_」以外にヒットします。[^a-zA-Z_]と同じです。
 \y は、英単語の区切りにヒットしますが、数字も単語の一部と見なす点で、「\<」や「\>」と少し意味が違ってきます。例えば「abc123」のような文字列があったとすると、その「abc」と「123」の間にはヒットしません。「abc xyz」という文字列があるとすると、「abc」とその次の空白の間および空白と「xyz」の間にはヒットします。「_」も英単語の一部と見なされます。Perlでは「\b」と書くことが多いようですが、HmJre.dllでは「\b」はバックスペース制御文字という扱いになっているので、「\y」となっています。
 \Yは、「\y」の反対で、英単語の区切りじゃない所にヒットします。
 これらの指定については、[...]および[^...]のキャラクタクラスの指定の中でも使えます。例えば[\d0-9]のように指定すると、半角数字と全角数字にヒットする条件が指定出来ます。(V3.04から指定出来るようになりました)


タグ指定出来ない括弧 (V3.00から)
括弧が二重以上になる場合、\1、\2等のタグ指定の対象となるのは、普通、一番外側の括弧だけとななります。
(?:.....)のような形で一番外側の括弧を囲むと、タグ指定の対象となるのが、その1つ内側の括弧となります。
例えば
(?:(111)(222)(333))
のような正規表現パターンを指定すると、\1で参照出来るのが(111)、\2が(222)、\3が(333)の部分となります。
(?:(?:(111)(222)(333))|(444))
のような指定をすると、もしもそのパターンが「444」にヒットした場合には、\1、\2、\3は存在しない扱いとなり、「111222333」にヒットした場合は、\4が存在しない扱いとなります。


メタ文字を文字と見なす (V3.02から)
 \Qで始まって\Eで終わるような形で文字列を書くと、その中の文字列の中では、いわゆるメタ文字が普通の文字扱いになります。
 例えば、"a.b"と書いた場合は、その中にある「.」はメタ文字での「任意の1文字」という意味になりますが「\Qa.b\E」と書くと、「a.b」という文字列そのものを表すことになります。
 文字列の最後まですべてを対象としたい場合は\Eは省略してもかまいません。例えば「\Qa.b」は「\Qa.b\E」と同じです。
 \Q\n\Eは、改行にはヒットしないで「\n」という文字列にヒットします。


コメント (V3.00から)
 (?#expression)のように書くと、その部分はコメント扱いとなり、正規表現のマッチング上は無視されます。
 他の正規表現ライブラリ等ではコメント内ではカッコのネストが使えないようですが、HmJre.dllではV3.17付近からカッコのネストが使えるようになっています。例えば(?#xxx(yyy)zzz)と書くと、それ全体がコメント扱いとなります。


類似検索 (V5.00から)
 (?#similar:数値)または(?#smilar:パーセント値)のように書くことで、類似検索およびその度合いを指定出来ます。数値の所には許容するミスの数、いわゆる「レーベンシュタイン距離」を指定するか、または類似度合いをパーセンテージで指定します。
(?#similar:2)program
 とすると、"program"の単語に対して2つのミスを許容する形で検索が実行されます。例えば"plogran"にヒットします。
(?#similar:80%)whitehouse
 とすると、"whitehouse"に対して類似度80% = 10文字中2文字のミスを許容する形で検索が実行されます。
 (?#similar:0)と指定すると、類似検索がOFFに戻ります。例えば
(?#similar:1)program(?#similar:0)code
 と指定すると、"program"部分は類似検索となり、"code"は普通の検索になります。例えば"program"に対して1文字違う"plogramcode"に対してはうまくヒットしますが、"code"部分に対して1文字違う"programcoda"にはヒットしません。
 類似度合いをパーセンテージで指定すると、例えば80%を指定した場合、単語の文字数が10文字なら2文字までミスを許容するようになります。パーセンテージで指定できるのは50%〜99%までの数値となります。
 ミスの数を数値で指定する場合で、ミスの数が単語の文字数の半分を超える場合は、自動的に半分までの扱いとなります。
 検索文字列の長さが2文字以下、または255文字以上の場合は類似検索の指定は無視され、普通の検索扱いとなります。
 類似検索は繰り返しパターンの中でも有効となります。例えば
(?#similar:1)(test)+
 は、"test"に対して類似した"tset"とtst"と"teest"のどれにヒットするために、例えば"tsettstteest"に対してもヒットします。ただし、類似検索は普通の検索よりも何倍〜何十倍も遅いので、あんまり複雑な繰り返しパターンを指定するのはお勧めできません。

 HmJre.dllの類似検索での「ミス」は、「1文字余計なのが混じってる」、「1文字足りない」、「1文字他の文字になってる」の一般的な3種類のミスの他に、半角文字に限って「文字が入れ替わってる」も1ミスとカウントします。例えば"(?#similar:1)test"は、eとsの入れ替わった"tset"に対してもヒットします。
 類似検索の中での「文字の数」は、全角文字も1文字として数えます。また、ユニコードでのサーゲートペアを使った文字も、正しく1文字とカウントします。
 HmJre.dllの類似検索では、先頭の1文字がミスした文字列には一切ヒットしません。例えば"(?#similar:1)test"は"est"にはヒットしません。
 類似検索と他の正規表現パターンの組み合わせをした場合でも、一応うまくヒットするはずです。例えば
(?#similar:1)test(?#similar:0)[a-z]
 は"testx"に対してヒットするだけじゃなくて、"test"にもヒットします。この場合、"(?#similar:1)test"部分が"tes"にミス1相当でヒットしてることになります。


その他
 他の正規表現パターンについては、秀丸エディタのヘルプなりJRE32.DLLの説明なりを参照ください。
 JRE32.DLLとの互換性を多少なりとも確保するために、{n}などの形式で間違いがあってもエラーにはなりません。例えば「a{」が指定された場合は、それは{n}などの指定ではなく、単に「a{」という文字列を検索する指定であると解釈されます。



戻る