＞秀丸マクロのいろはにほへと

# 第III部〜秀丸マクロのいろはにほへと
マクロ内での「\」や特殊文字の使い方

## マクロ内での「\」や特殊文字の使い方

- 【０】まえがき 〜 「\」や特殊文字を表記するために 〜
- 【１】「\」の意味
- 【２】「\」の使用例
- 【３】正規表現で使用する場合
- 【４】補足

### 【０】まえがき 〜 「\」や特殊文字を表記するために 〜

秀丸マクロで文字列を書きたいときには、" "（ダブルクォーテーションマーク：二重引用符）でくくってテキストファイル上に書きます。

ということは、その二重引用符の間に「二重引用符自体」とか「改行文字」とかを書きたいと思った場合に、どうすればよいでしょうか？
秀丸マクロの場合、これらはＣ言語と同様の書式を用いることで書き表すことができます。
具体的には、このような特殊文字は半角の「\」とその後ろに特定の文字を組み合わせることによって書き表す、という「きまり」になっています。

逆にいうと、「\」の文字を書きたいときに単に「\」と書くとよろしくないということになります。

以下では、これらの特殊文字や「\」自体を表記したい時の書き方を簡単にまとめてあります。

秀丸エディタ Ver.8.66以降では、C++11のRaw文字列リテラルやC#の逐語的リテラル文字列 記法が使用出来るようになりました。この記法を使用すれば、「\」によるエスケープなしで、記述した文字列をそのまま、変数に入力できます。
(記法によっては制限があります。「Ver.8.66以降の場合」を参照)

秀丸エディタ Ver.9.19以降では、C# 11 Raw string のような記法も使えます。(「Ver.9.19以降の場合」を参照)

### 【１】「\」の意味

「\」を使う場合として、次のものが挙げられます。

エスケープシーケンスの例
\t | タブ | 16進数の「09」、10進数の「9」
\n | 改行 | 16進数の「0A」、10進数の「10」
\" | 「"」自身 | 16進数の「22」、10進数の「34」
\\ | 「\」自身 | 16進数の「5C」、10進数の「92」
\x hh | 任意の文字コード hh の文字 (16進数) | 例えば「\x41」で、16進数の「41」、 10進数の「65」。これは文字でいうと「A」です。
\u hhhh | 任意のユニコードで指定する文字 (16進数4桁固定) | 「`\u79C0`」で、「秀」という文字を示す。 16進数4桁までなので、コードポイントが 0x10000を超える場合は、サロゲートペアで表現する必要がある。 𠀋(`U+2000B`)は、 上位サロゲート `\uD840` 下位サロゲート `\uDC0B` のように2文字文を使う表現になる。
\U hhhhhhhh | 任意のユニコードで指定する文字 (16進数8桁固定) | 「`\U000079C0`」で、「秀」という文字を示す。 𠀋(`U+2000B`)は、`\U0002000B` という表現になる。(Ver.8.52)

試しに、以下のマクロを実行してみてください。
@ と @ の間の表示に注目してみてください。

    //---- 「\」の扱いを調べるテストマクロ ---------------------
    $str[1] = "\t";
    $str[2] = "\n";
    $str[3] = "\"";
    $str[4] = "\\";
    $str[5] = "\x41";
    $str[6] = "\u79C0";
    $str[7] = "\uD840\uDC0B";
    $str[8] = "\U0002000B";
    #i = 1;
    while( $str[#i] != "" ) {

        message "@" + $str[#i] + "@";
        #i = #i + 1;

    }
    endmacro;
    //---- ここまで --------------------------------------------

### 【２】「\」の使用例

では、実際に「\」が出てくるマクロをいくつか書いてみましょう。

(a)ファイル「c:\test.txt」をオープンするマクロ

    //---- ファイルをオープンするテストマクロ ------------------
    openfile "c:\\test.txt";
    endmacro;
    //---- ここまで --------------------------------------------

ファイル名に「\」という文字を使いたい訳ですから、「\」自身の文字を表すために「\\」と表記します。

(b)改行を挿入するマクロ

    //---- 改行を挿入するテストマクロ --------------------------
    insert "改行する文章\n改行した後の文章";
    endmacro;
    //---- ここまで --------------------------------------------

改行を表現したい時は、「\n」でしたね。

(c)正規表現による改行検索を行うマクロ

実は、正規表現による検索・置換をする場合には、\の使い方が一見変わっているように見えます。【３】の例をごらんください。

### 【３】正規表現で使用する場合

    //---- 改行検索を行うテストマクロ -------------------
    searchdown "\\n", regular;
    endmacro;
    //---- ここまで -------------------------------------

この表記だと、二重引用符の中は「改行文字」ではなく「\nという２文字の文字列」になっています。「\\」が、\という文字自身を表していますので、そうなりますね。
でも、正規表現による検索・置換をする場合にはこれでよいのです。というか、このように表記しなければいけません。

なぜそうなるのかを説明するために、少し難しくなりますが秀丸エディタの内部動作を説明します。

秀丸エディタは正規表現による検索・置換をするために、HMJRE.DLLというプログラムを利用しています。秀丸エディタはHMJRE.DLLに、検索文字列を渡します。 HMJRE.DLLは渡された文字列を「解析」してその中に「\nという２文字の文字列」が有った場合、それを「改行文字」だと「解釈」をします。
つまり、HMJRE.DLLに渡す文字列にもマクロで表記するのと同様な「表記のきまり」があるということです。だから、改行文字を検索させたい場合は HMJRE.DLL に対して「\nという２文字の文字列」を送ってあげる必要があって、そのためには秀丸エディタのマクロ文では「\nという２文字の文字列」を記述してあげればよいことになっています。

というわけで、searchdown 文の引数として「\nという２文字の文字列」を記述してあげればよいので、 `"\\\\n"`という書き方になるのです。

上記のマクロを見て、「あれっ、改行って確か「\n」だから、「`searchdown "\\n",regular;`」じゃないの。試しに動かしたら、ちゃんと検索したぞー」とおっしゃる方もおられると思います。
これは、HMJRE.DLLが一応「改行文字そのもの」を送られてきた場合にも対応しているから動作しています。が、これは一般的な表記ではないので、複雑な文字列になると検索できない場合があります。というわけで、`"\\\\n"`と書くようにしましょう。

この表記法は改行だけに限らず、\を使う表記すべてに当てはまります。ということで、たとえばタブ文字を検索したい場合は

    searchdown "\\t", regular;

となりますし、\ という１文字を（正規表現中で）検索したいときには

    searchdown "\\\\", regular;

となるわけですねヾ(^^;

＃このように\を重ねて書かねばならないのはマクロ内だけです。正規表現による検索でもダイアログで普通に行う分には\は１個でよいです。

慣れてくると逆に混乱することがあるので、蛇足ですが(^^;)。

では、正規表現のマクロ記述は何でも\を重ねて書けばよいかというと、ダブルクォーテーションマーク(" )だけは異なります。

    searchdown "\"", regular;

が正解です。ダブルクォーテーションマークは制御文字でなく普通の文字なので、\" でダブルクォーテーションマーク１文字をHMJRE.DLLに渡せるからです。あるいは、以下のようにして「\"という２文字の文字列」をHMJRE.DLLに渡しても動作します。

    searchdown "\\\"", regular;

もし、マクロ内で正規表現がうまく動かない場合は、使用する正規表現を message文で表示してみてください。表示される内容がHMJRE.DLLに渡される文字列となるので、実際にどのような文字列が渡されているのか確認出来ます。

### 【４】補足

- Ver.8.54以降の場合
- Ver.8.66以降の場合
- Ver.9.19以降の場合

#### Ver.8.54以降の場合

秀丸エディタ Ver.8.54以降では、 quote 関数が使えます。

この関数は、正規表現で使用されるメタ文字の前に"\"を追加し、エスケープします。 (正規表現で、その文字そのものとして扱われるようにする。秀丸エディタのヘルプ-正規表現の後半を参照)

現状では、以下の文字が対象になっています。

    [ ] ( ) ^ $ . * + ? | \ { }

この文字列を、quote 関数で変換すると以下のように、各文字の前に"\"が追加された文字列を返します。

    \[ \] \( \) \^ \$ \. \* \+ \? \| \\ \{ \}

秀丸エディタのパスを入力してみます。

    C:\Program Files\Hidemaru\Hidemaru.exe

quote 関数の戻り値は以下になります。

    C:\\Program Files\\Hidemaru\\Hidemaru\.exe

この戻り値を正規表現の検索で使用すれば、"`C:\Program Files\Hidemaru\Hidemaru.exe`" を、間違いなく検索可能になります。

#### Ver.8.66以降の場合

秀丸エディタ Ver.8.66以降では、C++11のRaw文字列リテラルや、C#の逐語的リテラル文字列 の記法が使用出来るようになりました。この記法を使えば、文字列を見やすく記述可能になります。

Raw文字列リテラル
  秀丸マクロヘルプ - 式について - 文字列の「R"」から始まる文字列を参照 Raw文字列リテラルは、「R」から始め、以降「"」「Keyword」「(」と続き、ここまでが先頭を示す文字列になります。その後に文字列を記述し、「)」「Keyword」「"」の文字列で終端を示します。

  Raw文字列リテラル
  通常 | "文字列"
  Raw文字列リテラル | R"Keyword(文字列)Keyword"

  - 「Keyword」は、前後に同じ文字列を使用する必要があります。
  - 「Keyword」は、0文字以上なので省略も可能です。省略する場合は、前後の「Keyword」を省略します。
  - 文字列中に括弧「( )」を使う場合には、「Keyword」を付けておくと、先頭と終端の括弧と区別できます。
  簡単な記述例

      message R"hidemaru("Raw文字列リテラル"の記述例です。)hidemaru";
      //        "hidemaru"が「Keyword」になっている。

      message R"("Raw文字列リテラル"の記述例です。)";
      //      「Keyword」は省略可能

      message R"hidemaru("Raw文字列リテラル(Raw String Literal)"の記述例です。)hidemaru";
      //      文字列中に括弧を使用する場合は、「Keyword」を付けておくといいです。

      message R"("Raw文字列
      リテラル"の記述例です。)";
      //      改行もそのまま改行と認識される。

      message R"("Raw文字列
      リテラル"の記述例です。
      "\"マークやダブルクォートもそのまま表示されます。
      "C:\Program Files\Hidemaru\Hidemaru.exe")";

      message R"("Raw文字列
      リテラル"の記述例です。
          インデントもそのまま文字列扱いされます。)";

逐語的リテラル文字列
  秀丸マクロヘルプ - 式について - 文字列の「@"」から始まる文字列を参照 逐語的リテラル文字列は、「@"」から始まり、文字列を記述し、「"」で終わります。

  逐語的リテラル文字列
  通常 | "文字列"
  逐語的リテラル文字列 | @"文字列"

  - 文字列中に「"」を記述する場合は「""」とする必要があります。
  簡単な記述例

      message @"""Raw文字列リテラル""の記述例です。";

      message @"""Raw文字列
      リテラル""の記述例です。";
      //      改行もそのまま改行と認識される。

      message @"""Raw文字列
      リテラル""の記述例です。
      ""\""マークはそのまま表示されます。
      ""C:\Program Files\Hidemaru\Hidemaru.exe""";

      message @"""Raw文字列
      リテラル""の記述例です。
          インデントもそのまま文字列扱いされます。";

例として「message文」を使いましたが、文字列を指定する箇所なら何処でもこの記法が使えます。正規表現パターンを指定する場合にも使用できるので、見やすくなります。

また、ファイルパスを記述する際に、エクスプローラ等からコピーした文字列をそのまま使う事もできます。

    openfile @"C:\Program Files\Hidemaru\HIDEMARU.TXT";

#### Ver.9.19以降の場合

秀丸エディタ Ver.9.19以降では、C# 11 Raw string のような記法も使えます。

- 秀丸マクロヘルプ - 式について - 文字列の「"""」から始まる文字列を参照
- Raw string literals - """ - C#

「"""」から始め、「"""」で末尾と判断します。「"(ダブルクォート)」の連続数は3個以上あればよく、先頭と末尾の個数は同じにする事。

- 一行で書く場合は、単純にで囲むだけです。

      message """先頭と末尾は3個なので、""(2個) まではそのまま記述可能""";

- 複数行で書く場合は注意が必要です。

  - 「先頭」の直後に文字列は記述できません。すぐ改行する必要がありますが、「先頭」直後の改行は無視されます。
    「末尾」直前の改行とタブ・空白によるインデントは無視されます。「末尾」の直前は、改行またはタブ・空白によるインデントのみ許容されます。

        $header = "### start ###";
        $text   = """
        "先頭"と"末尾"は3個なので、""(2個) まではそのまま記述可能
        """;
        $footer = "### end ###";
        debuginfo 2;
        debuginfo $header + $text + $footer;
        endmacro;

    実行結果。
    「先頭」直後の改行と、「末尾」直前の改行とタブ空白によるインデントも無視されるので、全部つながって1行になっている。

        ### start ###"先頭"と"末尾"は3個なので、""(2個) まではそのまま記述可能### end ###

    「先頭」直後と「末尾」直前の改行が無視されるだけなので、空行を入れておけば改行可能。

        $header = "### start ###";
        $text   = """

        "先頭"と"末尾"は3個なので、""(2個) まではそのまま記述可能

        """;
        $footer = "### end ###";
        debuginfo 2;
        debuginfo $header + $text + $footer;
        endmacro;

    実行結果。
    空行は改行と認識され、3行で出力される。

        ### start ###
        "先頭"と"末尾"は3個なので、""(2個) まではそのまま記述可能
        ### end ###

  - インデント

    インデントも可能ですが、ベースライン(基準)は「末尾」の先頭になります。ベースライン(基準)より前のインデントは無視され、ベースライン(基準)より後のインデントは有効です。

    ベースライン(基準)より前には、タブ・空白によるインデントのみ許容されます。

        $header = "### start ###";
        $text   = """

                  インデントなし
                    インデント有り
                  下の行はインデントが「末尾」と同じなので空行扱いされる。

                  """;
        $footer = "### end ###";
        debuginfo 2;
        debuginfo $header + $text + $footer;
        endmacro;

    実行結果。
    空行は改行と認識される。

        ### start ###
        インデントなし
          インデント有り
        下の行はインデントが「末尾」と同じなので空行扱いされる。
        ### end ###

  - NGになる例

    1. 先頭の「`"""`」の後に改行以外の文字がある場合

           $text   = """「先頭」
           と「末尾」は3個なので、""(2個) まではそのまま記述可能
           """;

    2. 末尾の「`"""`」の前にインデント(空白かタブ)以外の文字がある場合

           $text   = """
           「先頭」と「末尾」は3個なので、""(2個) まではそのまま記述可能
           です。""";

    3. 末尾の「`"""`」のインデント(空白かタブ)より前に文字がある場合

           $text   = """
           「先頭」と「末尾」は3個なので、""(2個) まではそのまま記述可能
               """;

ページトップ 目次に戻る