last updated:2023/12/27

Hidemaru Q and A

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


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

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

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

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

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

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

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

【1】「\」の意味

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

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

【2】「\」の使用例

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

searchdown "\\t", regular;

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

searchdown "\\\\", regular;

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

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

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

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

searchdown "\"", regular;

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

searchdown "\\\"", regular;

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

【4】補足

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文字列リテラル

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以降では、Pythonのヒアドキュメントのような記法も使えます。

「"""」から始め、「"""」で末尾と判断します。「"(ダブルクォート)」の連続数は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;
    • NGになる例

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

        $text   = """「先頭」
        と「末尾」は3個なので、""(2個) まではそのまま記述可能
        """;
      2. 末尾の「"""」の前にインデント(空白かタブ)以外の文字がある場合

        $text   = """
        「先頭」と「末尾」は3個なので、""(2個) まではそのまま記述可能
        です。""";
      3. 末尾の「"""」のインデント(空白かタブ)より前に文字がある場合

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

ページトップ 目次に戻る