Meryの正規表現 鬼車 置換 後方参照

  1. この投稿は削除されました。

     |  もいすん  |  返信
  2. この投稿は削除されました。

     |  もいすん  |  返信
  3. (再投稿します) m(_ _)m
    [意見] Mery エディタの正規表現について(経験者のために)

    Mery の正規表現は、鬼車 Version 5.9.2 (onig.dll) を使います。

    ・ 正規表現文法の資料

    鬼車 (日本語: EUC-JP)
    http://www.geocities.jp/kosako3/oniguruma/index_ja.html
    ドキュメント 正規表現 (日本語: EUC-JP)
    http://www.geocities.jp/kosako3/oniguruma/doc/RE.ja.txt

    ・ 添付の 鬼車 (onig.dll) は、

    Mery 1.1.2.2840(2010/10/22)
    :onig.dll(2007/12/22):鬼車 Version 5.9.1(2007/12/22)
    Mery 2.0.0.3583(2012/07/02)
    :onig.dll(2012/07/01):鬼車 Version 5.9.2(2010/01/09)
    … 同一版、
    Mery 2.0.8.3919(2012/09/01)
    :onig.dll(2012/07/01):鬼車 Version 5.9.2(2010/01/09)

    ・ つぎの機能で、鬼車の正規表現が使えます。
    ○ 検索
    検索 → 検索 →
    □大文字と小文字を区別する にチェック
    □正規表現を使用する にチェック
    → 検索する文字列

    ○ 置換
    検索 → 置換 →
    □大文字と小文字を区別する にチェック
    □正規表現を使用する にチェック
    → 検索する文字列 置換する文字列

    ○ ファイルから検索
    検索 → ファイルから検索 →
    □大文字と小文字を区別する にチェック
    □正規表現を使用する にチェック
    → 検索する文字列

    ○ ファイルから置換
    検索 → ファイルから置換 →
    □大文字と小文字を区別する にチェック
    □正規表現を使用する にチェック
    → 検索する文字列 置換する文字列

    ○ 編集モード
    表示 → 編集モード → 編集モードの設定
    (→ 編集モードを選ぶ、または新規作成)
    → プロパティ → 強調 (→ 文字列を選び、また追加)
    → □大文字小文字を区別 にチェック
    → □正規表現 にチェック

    ○ アウトライン
    アウトライン → プロパティ → タイプ : カスタム
    → □ にチェック → 検索/正規表現

    ○ マクロ
    selection インターフェイス や Editor インターフェイス の
    検索/置換メソッド

    ※ 注意 ※
    マクロの中の JavaScript の検索と置換( test や replace )では、
    鬼車の正規表現は使えません。
    JavaScript のドキュメントにある正規表現を参照してください。

    マクロの記述であっても Mery メソッドの Find や Replace は鬼車を
    使います。

    ・ Mery の内部から鬼車を使う文字エンコーディングは UTF-16LE の Unicode 16bit
    リトルエンディアン。

    たとえば、M (半角)の符号化バイトによる検索は、2バイト(16bit)連続
    表記でないと一致しません。
    \115\000 … 八進数表現(符号化バイト)
    \x4d\x00 … 十六進数表現(符号化バイト)

    ・ \x{7HHHHHHH} 拡張十六進数表現(コードポイント値)が使えます。サロゲートペア
    でも有効。

    たとえば、H22常用漢字の1字、
    [𠮟] しか・る は4バイト Unicode (UCS-4 サロゲートペア) に含まれていて
    𠮟 U+20B9F \uD842\uDF9F

    これを
    \x{20b9f}
    のようにコードポイントで検索できます。

    ※ 通常は文字コード(コードポイント値)が表示される Mery のステータス
    バーには、サロゲートペアを区別していない、第1文字目のコード D842 が
    表示されます。(2.0.8.3919)
    しかし、\x{d842} で検索してもこの文字には一致しません。

    ほかの2バイト Unicode (UCS-2) もコードポイントで、
    剝 U+525D \u525D
    塡 U+5861 \u5861
    頰 U+9830 \u9830
    は、それぞれ
    \x{525d}
    \x{5861}
    \x{9830}
    として検索できます。

    また、これは文字集合として、
    [𠮟剝塡頰]
    で検索できます。

    この例に使った4文字は、
    H22常用漢字の中で、JIS X0208 や シフトJIS に含まれていない、要注意
    文字です。

    この 4字には JIS X0208 と UCS-2 BMP に含まれる、異なるが類似した文字が
    あって、従来はこちらを使用していました。
    叱 U+53F1 \u53F1
    剥 U+5265 \u5265
    填 U+586B \u586B
    頬 U+982C \u982C

    それぞれ
    \x{53f1}
    \x{5265}
    \x{586b}
    \x{982c}
    として検索できます。

    ※ JavaScript の正規表現では、たとえば全角空白 は、\x{3000} ではなく、
    \u3000 と表記します。

    ※ Mery 1.1.2.2840 ではサロゲートペアは半角空白2字で表示され、コードの
    保持、保存・読込み、検索・置換は動作します。ただし、UTF-8 の正しい値では
    なく、不正字の全角2字で保存されます。

    ・ 検索文字列の正規表現の文字列長

    これまでに Mery 1.1.2.2840 で動作させたことのある正規表現の最長は、
    約7200文字です。実際の限界値はわかりませんが、Mery の行の長さが 8000
    文字までと MeryWiki のよくある質問に書かれていますので、少なくとも同
    じ程度の上限ではないかと予想しています。
    ということで、通常に作成する正規表現では、制限を意識せずに、実用上で
    十分な長さの式を使用できることになります。

    ・ 検索文字列の正規表現の入れ子レベル・再帰レベルの深さ

    これまでに Mery 1.1.2.2840 で動作した正規表現で深い入れ子は 150階層
    くらいまで。再帰ではさらに深い階層まで正しく処理できています。
    バグで停止条件を誤った終わりのない再帰でも、無反応になるまで動作が続
    き、繰り返しが中断されることはありません。
    おそらく、メモリ限度まで、という Mery の編集機能と同じでしょう。

    ・ 鬼車のオプション

    Mery の内部から鬼車を使用する際に、つぎのオプションが有効になって
    います。(これまでの Mery 1.1.2.2840 では無効)

    G: ONIG_OPTION_CAPTURE_GROUP

    これによって、名前付き捕獲式集合 (?<name>式), (?'name'式) を使うとき
    に、同時に使う捕獲式集合 (...) の振舞が変化します。
    これまでの、
    (...) は、非捕獲式集合として扱われる。
    番号指定参照/呼び出しは不許可。
    から、
    (...) は、捕獲式集合として扱われる。
    番号指定参照/呼び出しは許可。
    になります。

    (RE.ja.txt より抜粋)
    ---------------------------------------------------------------------------
    > 7. 拡張式集合
    > (式) 捕獲式集合
    > (?:式) 非捕獲式集合
    > (?<name>式), (?'name'式)
    > 名前付き捕獲式集合
    > 式集合に名前を割り当てる(定義する)。
    > (名前は単語構成文字でなければならない。)
    ---------------------------------------------------------------------------
    △ これまでは、
    名前付き捕獲式集合を使うとき、
    名前付き捕獲式集合 (?<name>式), (?'name'式) と 捕獲式集合 (...) は
    混在できず、捕獲式集合 (...) は、非捕獲式集合 (?:式) と同じに扱われ、
    式集合(グループ) としてのみ機能して、値を捕獲しない。
    後方参照
    ネストレベル付き後方参照
    部分式呼出し
    では、
    名前指定参照 だけで、番号指定参照 などはできない。
    (名前付き捕獲式集合を使わないときに限って、番号指定参照 などが
    できる。)

    ◎ 新しい Mery では、
    名前付き捕獲式集合を使うとき、
    名前付き捕獲式集合 (?<name>式), (?'name'式) と 捕獲式集合 (...) は
    混在できる。どちらの集合も、値を捕獲し、式集合(グループ) となる。
    後方参照
    ネストレベル付き後方参照
    部分式呼出し
    では、
    番号指定参照
    相対番号指定参照
    名前指定参照
    を混在させることができる。
    (名前付き捕獲式集合には、名前だけでなく、同時に番号も割り当てられ
    ている。)

    (RE.ja.txt より抜粋)
    ---------------------------------------------------------------------------
    > 8. 後方参照
    > \n 番号指定参照 (n >= 1)
    > \k<n> 番号指定参照 (n >= 1)
    > \k'n' 番号指定参照 (n >= 1)
    > \k<-n> 相対番号指定参照 (n >= 1)
    > \k'-n' 相対番号指定参照 (n >= 1)
    > \k<name> 名前指定参照
    > \k'name' 名前指定参照

    > ネストレベル付き後方参照
    > level: 0, 1, 2, ...
    > \k<n+level> (n >= 1)
    > \k<n-level> (n >= 1)
    > \k'n+level' (n >= 1)
    > \k'n-level' (n >= 1)
    > \k<name+level>
    > \k<name-level>
    > \k'name+level'
    > \k'name-level'
    >
    > 9. 部分式呼出し ("田中哲スペシャル")
    > \g<name> 名前指定呼出し
    > \g'name' 名前指定呼出し
    > \g<n> 番号指定呼出し (n >= 1)
    > \g'n' 番号指定呼出し (n >= 1)
    > \g<-n> 相対番号指定呼出し (n >= 1)
    > \g'-n' 相対番号指定呼出し (n >= 1)
    ---------------------------------------------------------------------------

    ・ 置換後の文字列に使える鬼車の後方参照

    これまでの Mery では、正規表現を検索文字列として置換をするとき、
    置換後の文字列 の中には、つぎの後方参照が使えます。
    \1 … 番号指定参照1。左から1盤目にある 捕獲式集合 (...) の値
    \2 … 2
    \3 … 3
    \4 … 4
    \5 … 5
    \6 … 6
    \7 … 7
    \8 … 8
    \9 … 番号指定参照9。左から9盤目にある 捕獲式集合 (...) の値
    10番目以降は参照しません。2桁目以上に数字があれば、その数字は
    そのまま文字列として扱われます。
    後方参照でその番号の捕獲式集合がないときは、空文字列になります。
    つぎの文字は制御文字となります。
    \a … 鐘 (0x07)
    \t … 水平タブ (0x09)
    \n … 改行 (0x0a)
    \v … 垂直タブ (0x0b) (一部の版では v )
    \f … 改頁 (0x0c)
    \r … 復帰 (0x0d)
    \e … 退避修飾 (0x1b) (一部の版では 0b )
    上記のほかの文字が \ に続けてあると、その文字そのものです。
    \0 … 0
    \\ … \
    \b … b
    \k … k

    ◎ 新しい Mery では、これに加えて、さらに使える後方参照が増えました。
    正規表現による置換をするところすべてで使えます。

    (これまで)
    \n 番号指定参照 (n >= 1 かつ n <= 9)
    (新)
    \k<n> 番号指定参照 (n >= 1)
    \k'n' 番号指定参照 (n >= 1)
    \k<-n> 相対番号指定参照 (n >= 1)
    \k'-n' 相対番号指定参照 (n >= 1)
    \k<name> 名前指定参照
    \k'name' 名前指定参照

    参照する捕獲式集合の数が、10より多くても \k の番号指定で指定できます。
    参照する番号と、文字列中の番号、のあいまいさを減らします。

    名前付き捕獲式集合 (?<name>式), (?'name'式) と 捕獲式集合 (...) の
    どちらにも番号が割り当てられるため、名前付き捕獲式集合も忘れずに数えて
    目的の集合の番号を計算します。

    相対番号指定参照は、最後に定義された(最も右にある)集合を \k<-1> また
    は \k'-1' として、左に向かって、-2、-3、-4、…と数えた番号で参照します。

    名前指定参照は、名前付き捕獲式集合 (?<name>式), (?'name'式) で定義され
    た name を使い、\k<name> または \k'name' として参照します。

    多重定義の名前付き捕獲式集合 (?<name>式), (?'name'式) を名前指定参照
    すると、最後に定義された値を参照します。
    (検索では、最後で一致しないときに順に前に定義された値との一致を探して
    いきますが、置換の参照ではこの動作をしません。)

    該当する番号または名前の捕獲式集合がない参照は、空文字列になります。
    不完全な参照となる文字も、空文字列となります。
    \k<0>
    \k'0'
    \k<->
    \k'-'
    \k<
    \k'
    \k<>
    \k''

    ※ ネストレベル付き後方参照と、部分式呼出しは、置換後の文字列では使え
    ません。もちろん検索では使えます。

    鬼車の正規表現で、後方参照の4つの書式すべてを、置換(置換後の文字列)で使用
    できるテキストエディタは、とても希少で価値があります。

    先読み/戻り読み/否定先読み/否定戻り読み/ネストレベル付き後方参照/部分式
    呼び出し-入れ子と再帰/などの拡張文法が使えて、許容する正規表現に制約が少な
    い上に、動作速度にストレスがなく結果表示が速い。これらはみな Mery エディタの
    正規表現の大きな特長となっています。

    編集操作としての検索・置換で使うだけでも、十分に効果を発揮します。でもさらに、
    Mery の応用範囲を飛躍的に広げる、マクロから利用できることで、ほかに類を見ない
    鬼車正規表現のすばらしい実用環境が生まれた、と言ってもよいと思います。
    また、正規表現の入門、応用の学習用具としてもきっと役立ちます。

    (終わり)

     |  もいすん  |  返信
  4. たとえば…、

    ・ アウトライン・プラグインのカスタムで使う正規表現と置換

    前に記事のコメントとして書いた、カスタム用の正規表現「インデント」
    を例にして、相対番号指定参照を使ってみます。
    この正規表現では、アウトラインに表示する内容を、置換で \3 として
    いました。左から3番目に定義された括弧(捕獲式集合)の値を参照、
    ということです。

    もしも、それより前の部分を変更して、括弧の数が1つ増えたときは、
    すべてのレベルで、正規表現のほかに、置換も \4 に書き換えなければ
    なりません。

    ここで、\3 の代わりに、相対番号指定参照の \k<-1> を使うと、最後
    に定義した括弧の値をいつも参照するので、書き換える必要がありませ
    ん。括弧の数を数える手間が省けるのもラクです。

    また、このアウトライン表示では、もし行の最初に、
    ○ さいしょの文
    のように、1文字(記号や番号)と、半角空白1桁があると、それを除
    いて表示するようにしてあります。
    そして、この除いた部分を \2 で参照できるように括弧をつけていて、
    ここを除かずに表示するためには、置換を \2\3 とします。

    これは、相対番号指定参照では、\k<-2>\k<-1> と書きます。

    すこし寄り道で…、
    似た表記の、\g<1> は、部分式呼出しです。
    1番目に定義された括弧 ( {2}|\x{3000}|\t) の中の式を、この場所で
    もう一度、動作(評価)させます。定義したところで動作(評価)した
    結果(の値)とは別に、この場所での動作結果(値)が得られます。

    この式だと、半角空白2桁か、全角空白か、タブ記号、のどれか、とい
    う判定を改めてこの場所でします。最初の定義をしたところでは、半角
    空白2桁だったけれども、ここでは全角空白、というときも一致します。

    ここでは (?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end) の中に \g<1>
    があります。これは、先読み否定、ここから始まる内容がこうでなかっ
    たら一致、という、ややこしい条件です。ですので、さきほどの3つの
    空白文字のいずれでもなかったら、と判定していることになります。

    この空白文字の判定だけなら、[^ \x{3000}\t] でもよさそうですが、
    これだと、半角2桁のときは否定、という条件にならず、1桁でも否定
    してしまいます。ここは、インデント判定なので、タブ幅の空白を判別
    したかったため、先読み否定を使いました。

    では、今回は、名前を少し変えて…、

    ○ アウトライン・プラグインのカスタム正規表現: インデントでアウトライン

    インデントの段数を、アウトライン表示のレベルにする。
    半角空白、タブ、全角空白の混在するインデントも可。

    インデントの空白部分を除いた文字列には \k<-1> で置換。

    閉じ括弧、行コメント、ブロック終了句、は表示から除外。
    ) } ] # ' ; */ end

    行の最初に、1字と半角空白1字、があると表示から除外。
    ○ さいしょの文

    さいしょの文

    ○ タブの桁数 2
    正規表現
    ^(?:((?!(?: |\x{3000}|\t|[\)\}\]#';]|\*/|//|--|(?i)end)))(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){1}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){2}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){3}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){4}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){5}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){6}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {2}|\x{3000}|\t){7}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$

    置換
    \k<-1>

    タブの桁数 2 を 4 にするには、
    2ヶ所、
    {2} を {4} に、
    \x{3000}|\t を \x{3000}{2}|\t に、
    書き換え。

    ○ タブの桁数 4
    正規表現
    ^(?:((?!(?: |\x{3000}|\t|[\)\}\]#';]|\*/|//|--|(?i)end)))(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){1}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){2}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){3}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){4}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){5}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){6}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$
    ^(?:( {4}|\x{3000}{2}|\t){7}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$

    置換
    \k<-1>

    さらに、タブの桁数 4 を 8 にするには、
    2ヶ所、
    {4} を {8} に、
    {2} を {4} に、
    書き換え。

    ※ 置換の機能はありませんが、このアウトライン表示は Mery 1.1.2.2840 でも
    できます。
    ○ 1.1.2.2840 はレベル 9 まで。

    タブの桁数 2
    ^(?:( {2}|\x{3000}|\t){8}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$

    タブの桁数 4
    ^(?:( {4}|\x{3000}{2}|\t){8}(?! |\g<1>|[\)\}\]#';]|\*/|//|--|(?i)end)(. )?(..*?))$

    (本文のすべてが、アウトラインに表示されてしまうので、「空白の数」より、
    表示が混みあいます、あしからず。)

     |  もいすん  |  返信
  5. たとえば…、

    ・ 編集モードの強調で使う正規表現

    強調ではキーワードの単語をそのまま、強調文字列に登録して、選択し
    た種類の強調表示をする使い方が基本です。

    この強調文字列は、 259文字までを受け付けます。

    ここに正規表現を登録すると、その正規表現が一致したところを強調表
    示することができます。

    VisualBasic を例にして、正規表現による強調文字列を使ってみます。
    同じキーワードが、その範囲の開始と終了の両方に使われる場合に、そ
    の開始だけを特に強調してみることにします。

    Function プロシージャと Sub プロシージャは、どちらも同じように、
    Function

    Exit Function

    End Function

    Sub

    Exit Sub

    End Sub
    の書式で、開始と同じキーワードに終了では End が前置きされ、中断
    は同じキーワードが Exit とともに使われます。

    キーワードの指定によって、開始も中断も終了も Function と Sub は
    同じ強調表示がされるので、メリハリがありません。そこで、開始だけ
    をさらに別の強調表示にします。

    Function には一致しても End Function と Exit Function には一致し
    ない正規表現を考えます。Sub もまったく同様ですので Function で説
    明してゆきます。

    キーワードを見つけたときに、その前にある文字列によって、一致する
    かしないか、を判定するには、鬼車正規表現の「戻り読み」と「否定戻
    り読み」を、そして、キーワードやその前にある文字列の、前後に連続
    した文字がないことを判定するために、「先読み」を使います。

    この例では、End や Exit と Function の間にある半角空白またはタブ
    記号は、1桁または2桁としました。

    目的の正規表現の例は、

    (?<=[ \t()']|\A|^)(?<!End[ \t]|Exit[ \t]|End[ \t]{2}|Exit[ \t]{2})(?:Function|Sub)(?=[\s()']|\Z)

    となります。

    行頭から始まるとき、行の途中から始まるときや終わるとき、行末で終
    わるとき、ファイル末尾で終わるとき、などを、前後にある「戻り読み」
    の (?<=[ \t()']|\A|^) と「先読み」の (?=[\s()']|\Z) で判定します。

    左右のいずれかがコメント文字(' 単一引用符)に接する場合も一致判
    定に含んでいますが、左にあって、コメントとなるときは、コメントの
    右側すべての強調表示が優先されるため、同時には強調表示されません。

    つぎにある (?<!End[ \t]|Exit[ \t]|End[ \t]{2}|Exit[ \t]{2}) は、
    4つの最上位(括弧に囲まれてグループになっていない)の、長さの異
    なる「否定戻り読み」判定となります。

    「戻り読み」には、一致する長さが可変となる文字列を判定できない、
    という制約があるのですが、鬼車では、この最上位の比較に限って、例
    外として、このような可変長の比較を許して動作します。
    このため、 | (OR) で並べられた条件には、同じ内容の繰り返しが目立
    ちますが、これらをまとめていません。

    これがある位置から前の文字列として、
    End または Exit のうしろに、半角空白またはタブ記号が、1桁また
    は2桁あったときは、
    一致しない、と判定する「否定戻り読み」条件です。

    そして (?:Function|Sub) は、非捕獲式集合(グループにするだけ)で
    キーワードを並べて、 Function または Sub ならば、と判定します。

    では、設定例を…

    ○ 編集モード: End Function と Exit Function ではない Function の強調表示

    End や Exit と Function の間にある半角空白またはタブ記号は、1桁
    または2桁という前提です。

    表示 編集モード 編集モードの設定 VisualBasic プロパティ → 追加
    → 強調 強調文字列

    大文字小文字を区別
    正規表現
    強調6 (クリックすると1~8の順に切替)

    (※ この強調文字列の上限長さは 259文字)

    追加をすると「新しい強調文字列」して編集できます。編集を終了した
    ら、文字列の外をクリックすると確定です。
    すでにある文字列は、ダブルクリックをすると、編集状態になります。

    強調文字列の正規表現は、

    (?<=[ \t()']|\A|^)(?<!End[ \t]|Exit[ \t]|End[ \t]{2}|Exit[ \t]{2})(?:Function|Sub)(?=[\s()']|\Z)

    とします。

     |  もいすん  |  返信
スポンサーリンク