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)

            とします。

     |  もいすん  |  返信