\Q〜\E 内にある \f という文字列の検索にNo.07593
としひろ さん 15/05/31 08:25
 
文字列変数に取り込んだ1行分の文字列と、同一行を検索して削除する、というマク
ロを作っています。
具体的な用途は、ファイルのフルパスが書かれた2つのテキストファイルの差分を取
る、というものです。

文字列に、\ が含まれているため、正規表現は使えないので、

gofiletop;
while( 1 )
{
  searchdown2 $s + "\n";  // $s に1行分の文字列
  if( ! result ) break;
  if( ! column ) deleteline;  // 行頭でない場合は同一行ではない
  else down;  // 次の行から検索
}

フルパスなので、検索したら行頭でないと言う事は、正常な状態ならあり得ないので
すが、念のため、この様なマクロで行っていました。
しかし最近、\Q〜\E というものがあるのを知り、これなら正規表現が使えるじゃな
いか!という事で

replaceallfast "^\\Q" + $s + "\\E\\n", "", regular, nocasesense;

これを試してみましたが、\f を含んだパス、例えば…

D:\abc\file.txt

と言った文字列には、どうやらヒットしない、という事が分かりました。
この問題についての回避方法はありますか?
置換前に文字列内を検索し \f が含まれているかどうかで方法を分ける、
というのも考えてみました、果たして \f だけでいいのか、分かりません。
他にも注意しないといけない文字列はありますか?

[ ]
RE:07593 \Q〜\E 内にある \f という文字No.07594
としひろ さん 15/05/31 08:34
 
>  else down;  // 次の行から検索

これでは、次の行の途中からの検索になってしまいますね。

  else { golinetop; down; }

としなければいけないでしょうか?

[ ]
RE:07593 \Q〜\E 内にある \f という文字No.07595
IKKI さん 15/05/31 13:21
 
としひろさん、こんにちは。ユーザーの IKKI です。

「そもそも、その作業をマクロで実装する必要があるのか?」という観点から回答さ
せていただきます。
ご期待に添う回答でなかったらごめんなさい。

> 具体的な用途は、ファイルのフルパスが書かれた2つのテキストファイルの差分を取
> る、というものです。
差分を取る機能は「内容比較」という名前で秀丸エディタに内蔵されています。
[ウィンドウ]-[他の秀丸エディタと内容比較...] でできます。

 ヘルプ: ウィンドウ系コマンド−複数の秀丸エディタのウィンドウを同時に使って
作業するためのコマンド

> 文字列変数に取り込んだ1行分の文字列と、同一行を検索して削除する、というマク
> ロを作っています。
同一行を削除する機能は「uniq」と呼ばれ、変換モジュールとして提供されています。

 uniq.hmf 改造版 (h-tom さん)
 http://homepage3.nifty.com/_htom/macro/macro_dll.html#label-159

> 文字列に、\ が含まれているため、正規表現は使えないので、
文字列中に含まれるメタキャラクタの前に「\」を付ければ OK です。次の文ででき
ます。

 loaddll "hmjre.dll";
 $$ptn = dllfuncstr("ReplaceRegular", "[()\\[\\]{}^$.*+?|\\\\]", $$1, 0, "\\
\\\\0", 2);

> 他にも注意しないといけない文字列はありますか?
メタキャラクタの一覧があります。

 ヘルプ: 検索系コマンド−正規表現

\Q〜\E 内部で \f が解釈されてしまう問題については、秀丸担当さんの回答を待ち
ましょう。

当方の環境は Windows 7 (64bit) + 秀丸エディタv8.54β5 (32bit) + HMJRE.DLL v4.
11 です。
(お使いの環境によって回答が変わる場合がありますので、ご質問の際は環境を書き
添えることをおすすめします)

[ ]
RE:07595 \Q〜\E 内にある \f という文字No.07596
としひろ さん 15/06/01 08:33
 
IKKI さん、ご回答有難うございます。

説明不足であり、また余計な事も書いてしまった様で申し訳ないです。
具体的な使用例を書いた方が分かりやすいかな?と思ったのが逆にアダとなってしま
ったかも知れません。

>「そもそも、その作業をマクロで実装する必要があるのか?」という観点から回答さ
>せていただきます。

マクロで行う必要があるのです。
今回の作業で扱うファイルは、他のマクロ中に生成されたものであり、
比較先のファイルもマクロから、そのファイル名規則によって開かれるものです。
そして、行削除した後も、さらにマクロ処理は続きます。

>差分を取る機能は「内容比較」という名前で秀丸エディタに内蔵されています。
>[ウィンドウ]-[他の秀丸エディタと内容比較...] でできます。

内容比較は、compfile文 でマクロからも実行できる様ですが、編集する(行削除す
る)ファイルが
必ずしも比較先のファイルの内容を全て含んでいるとは限らないので、違いが見つか
った位置に移動しても、
新たな行が追加されたのか欠損しているのか、これだけでは判断できません。
「差分を取る」という言い方は、誤解を生むものでしたね。

>同一行を削除する機能は「uniq」と呼ばれ、変換モジュールとして提供されています。

こう言うものがあるとは知りませんでした。
今回の話とは別に、同一行削除マクロというのも作ったりしていますので、これを使
ってみようと思います。
「uniq」を、2つのファイルの比較に使うにはどうしたらいいでしょうか?
例えば、以下のように…

newfile;
insert "〜ここから比較先ファイル〜\n";
insertfile "比較先ファイルパス"; // あるいは、コピー&ペーストで読み込む
if( ! column ) insert "\n";
insert "〜ここから編集するファイル〜\n";
insertfile "編集するファイルパス"; // あるいは、コピー&ペーストで読み込む
if( ! column ) insert "\n";

selectall;
filter "Uniq.hmf", "Uniq"; // 同一行削除

gofiletop;
beginsel;
searchdown "^〜ここから編集するファイル〜\\n", regular;
down;
delete; // 比較先ファイルの内容を削除

この「uniq」は同一行の内、必ずファイル先頭に近い方が残る、という事が保証され
ているものですか?
また、行の順序は変更されない、と決まっていますか?
もしそうなら、残った行は比較先ファイルには存在しない行だけ、という事になるで
しょうか…?

あと、nocasesense に相当するオプションはありますか?
同じファイルパスで、大/小文字が違うだけのフォルダやファイルは存在できませんが、
他の用途で、大/小文字を区別しないで比較したい場合があるかも知れませんので、
あると便利です。

>> 文字列に、\ が含まれているため、正規表現は使えないので、
>文字列中に含まれるメタキャラクタの前に「\」を付ければ OK です。次の文ででき
>ます。
>
> loaddll "hmjre.dll";
> $$ptn = dllfuncstr("ReplaceRegular", "[()\\[\\]{}^$.*+?|\\\\]", $$1, 0, "\
>\\\\\0", 2);

なるほど、これだけで出来てしまうんですね。
答えを見た後なら、やっている事を理解できますが、自力でこのコードを作る事は無
理です。
特に、ブラケット内でブラケット自身と「\」は扱いが違う…、ん〜頭がグルグルし
てきます。

文字列中のメタキャラクタを全て「\」でエスケープすればいいんじゃないか?とい
うのは、最初に考えました。
ただ、上記のようなスマートな方法ではなく、
http://hidemaruo.mydns.jp:81/helpsite/hidemaru/html/190_CmdSearch_Regular.html
ここに書いてある、12個のメタキャラクタを文字列配列に入れ、田楽DLLの "GSUB"
で置換するというものです。
やっている事は同じですかね?

$meta1[0]  = "\\"; $meta2[0]  = "\\\\"; // \ を最初に処理しないと変な事になる
$meta1[1]  = "[";  $meta2[1]  = "\\[";
$meta1[2]  = "]";  $meta2[2]  = "\\]";
$meta1[3]  = "(";  $meta2[3]  = "\\(";
$meta1[4]  = ")";  $meta2[4]  = "\\)";
$meta1[5]  = "^";  $meta2[5]  = "\\^";
$meta1[6]  = "$";  $meta2[6]  = "\\$";
$meta1[7]  = ".";  $meta2[7]  = "\\.";
$meta1[8]  = "*";  $meta2[8]  = "\\*";
$meta1[9]  = "+";  $meta2[9]  = "\\+";
$meta1[10] = "?";  $meta2[10] = "\\?";
$meta1[11] = "|";  $meta2[11] = "\\|";

// $s に検索したい文字列を入れておいて…
#i = 0;
while( #i < 12 ) {
  $s = dllfuncstr( "GSUB", $s, $meta1[#i], $meta2[#i], -1 );
  #i = #i + 1;
}
replaceallfast "^" + $s + "\\n", "", regular;

と書いてはみたものの、これで問題ないのかどうか確信が持てなく、またあまりス
マートな方法ではない様な気がして、使ってませんでした。
「!」はエスケープしなくてもいいのか?「?!」等と「?」でセットで使うので無視で
いいのか?など…
そう言う心配を無用にしてくれるのが「\Q〜\E」だったので、これはいい!と思った
のです。

>> 他にも注意しないといけない文字列はありますか?
>メタキャラクタの一覧があります。

「\Q〜\E」は「メタ文字を文字とみなす」ものですから、メタキャラクタは無視して
いいはず…と思います。
http://hidemaruo.mydns.jp:81/helpsite/hidemaru/html/190_CmdSearch_Regular_Esc.html

「\f(フォームフィード、文字コード12)は、タグ付き正規表現に使われるため非サ
ポートとなりました。」

この文にヒントがありそうですが、正直よく分かりません。
よく考えてみると「\f」はメタ文字ではないので、「\Q〜\E」でエスケープできない
は当然の事。
「\f」は特別な文字なので、そもそも秀丸の regular 検索で「\f」に注意しないと
いけないのは、「\Q〜\E」に限った事ではない、
という事ですかね?

もし「\f」のような特別な文字が他にないなら、メタ文字ではなく、これだけを置換
すれば済むかも…

// $s に検索したい文字列を入れておいて…
$s = dllfuncstr( "GSUB", $s, "\\f", "\\\\Ef\\Q", -1 );
replaceallfast "^\\Q" + $s + "\\E\\n", "", regular;

ちょっと試してみた所、一応これでうまく行きそうな感じですが、どうでしょうか?

「D:\abc\file.txt」 ならば
「D:\abc\ + \E + f + \Q + ile.txt」 という風に置換しておく、というものです。

環境:
Windows 8.1 Update 64bit、秀丸エディタ 8.51 32bit
アドイン/ビルトインDLL:
HmJre.dll 4.10、Hidemarnet Explorer with FTPS 3.03、秀丸ファイラーClassic 1.13
OS は 64bit ですが、秀丸関係は全て 32bit です。

[ ]
RE:07596 \Q〜\E 内にある \f という文字No.07597
K'zawa さん 15/06/01 15:23
 
としひろさん、こんにちは。
K'zawaです。

\Q〜\Eの間には、まずなによりも「\E」がだめです。

[ ]
RE:07597 \Q〜\E 内にある \f という文字No.07598
秀丸担当 さん 15/06/01 16:25
 

\Q〜\Eの間は、確かに\fができませんでした。
\fは正規表現より先に秀丸エディタ本体が独自に解釈するもので、できていませ
んでした。
\E以外は気にせず書けるようになったほうがいいと思います。
問題ないか慎重に考えて修正を検討したいと思います。
現在のバージョンにおいては、、\Q〜\E\\f\Q〜\Eとすることで回避は可能だと
思います。

[ ]
RE:07596 \Q〜\E 内にある \fという文字列No.07599
h-tom さん 15/06/01 20:02
 

h-tom です。

今回の様な件では、正規表現を使わない最初の方法が正しいと思いますよ。
K'zawaさんもして指摘していますが、結局"\Q"、"\E"の対処が必要になります。
(ファイル名に"\Q"、"\E"が含まれると、誤動作すると思う。)

//ここから
gofiletop;
 while( 1 )
 {
   searchdown2 $s + "\n";  // $s に1行分の文字列
  if( ! result ) break;
  if( ! column ) deleteline;  // 行頭でない場合は同一行ではない
  else{ golinetop2; moveto2 column, lineno + 1;} //折り返し行も考慮して、エ
ディタ的座標で、確実に次の行に移動させる。
}
//ここまで

先頭行を無視していいなら、
   searchdown2 "\n" + $s + "\n";  // $s に1行分の文字列
という方法もありますが、削除部分がちょっと面倒なので、置換の方が良いかな?
   replaceallfast "\n" + $s + "\n", "\n";

・"\f"に関して
  タグ付き正規表現のセパレータに使用されているので、その影響でしょうか、
  正規表現エンジンには、"\f"が削除された内容が送られていました。
    D:\abc\file.txt -> D:\abcile.txt
  hmjre.dllで、括弧によるタグ指定が可能になって時間も経つので、"\f"のタグ
  付き正規表現は、旧バージョンの互換性あたりに追い出して、デフォルト無効に
  したほうがいいのではないかと、個人的には思います。

・変換モジュールのuniq(改造版)に関して
  出力リスト内を検索し、見つからなければ内容を追加し、見つかれば追加しません。
  そのため、同じ行があった場合は、入力内容の先頭に近いほうが残り、後の方が削除
  されることになります。
  出力リストは vector ですので、入力した順を保持しています。
  nocasesense に相当するオプションはありません。

[ ]
RE:07599 \Q〜\E 内にある \fという文字列No.07600
秀丸担当 さん 15/06/02 14:47
 

>・"\f"に関して
>  タグ付き正規表現のセパレータに使用されているので、その影響でしょうか、
>  正規表現エンジンには、"\f"が削除された内容が送られていました。
>    D:\abc\file.txt -> D:\abcile.txt
>  hmjre.dllで、括弧によるタグ指定が可能になって時間も経つので、"\f"のタグ
>  付き正規表現は、旧バージョンの互換性あたりに追い出して、デフォルト無効に
>  したほうがいいのではないかと、個人的には思います。

()に移行して、\fは古いものとしたいところですが、\fを使っているマクロがあ
ったとして、ある日バージョンアップしたら突然動かなくなったということは避
けたいので、互換性は維持しなくてはいけないと思います。

\Q〜\Eの中の\fも、既に何らかの理由で書かれているマクロがあったとしたら互
換性を気にしなくてはいけないと思いましたが、そういうことはまず無いと思う
ので、修正しようと思います。

[ ]
RE:07596 \Q〜\E 内にある \f という文字No.07601
としひろ さん 15/06/02 20:50
 
K'zawa さんへ

> \Q〜\Eの間には、まずなによりも「\E」がだめです。

あ!そうですね。
じゃあ、「\E」も変換して… う〜ん、うまくないですね、こんな方法は。
所詮、私の考えることなどこの程度のものです。

秀丸担当 さんへ

> \fは正規表現より先に秀丸エディタ本体が独自に解釈するもので、できていません
>でした。

なるほど、そう言う事ですか。でも「\f」だけが特別と分かったので良かったです。

> 現在のバージョンにおいては、、\Q〜\E\\f\Q〜\Eとすることで回避は可能だと思
>います。

他の方の指摘通り、「\Q」、「\E」をどうするのかという問題もありますし、
これらが入れ子になってたらどうなるのか…ちょっと考えてもよく分からないので、
今回、「\Q〜\E」を使うのはやめる事にします。
修正については、私の理解を超える問題ですので、慎重に検討して下さい、としか言
えません。

h-tom さんへ

> 今回の様な件では、正規表現を使わない最初の方法が正しいと思いますよ。

そうですね。正規表現は使わない方が良さそうですね。
なぜ「\Q〜\E」を使いたかったと言うと、処理速度の問題です。
時には、数万行のファイルを比較する事もあって、数分かかる事もあるのですが、
どうやら「^ 〜 \n」を使って、行頭と行末を指定して置換するのが速いようなんです。
まあ、5分が3分になる、程度の違いですが…

> replaceallfast "\n" + $s + "\n", "\n";

この方法も試して見ましたが、最初の方法より更に時間がかかるようです。
秀丸エディタヘルプに「\nを使った検索は秀丸エディタに負荷がかかって遅くなる」
というような事が書いてありましたが、正規表現でなくても、影響が出るのでしょう
か。

> else{ golinetop2; moveto2 column, lineno + 1;} //折り返し行も考慮して、エ
>ディタ的座標で、確実に次の行に移動させる。

これは完全に見落としてました。一応、論理行を意識してマクロを書いているつもり
ですが、
linelen2、linecount2、等は使っているくせに、golinetop2 という文がある事を、
今の今まで知りませんでした。
golinetop、golineend、で論理行頭・行末に移動できるものと思い込んでいました。

golinetop;
down;

と書いてしまっているマクロが、果たしていくつあるのか…、確認が必要です。

uniq(改造版) についての説明もありがとうございました。

[ ]
RE:07600 \Q〜\E 内にある \fという文字列No.07602
colder さん 15/06/02 23:34
 
colderです
秀丸担当さん。
\fができるようになったとしても\Eができない問題が依然として残るので、
いっそのことマクロにPerlのquotemeta関数に相当する関数を追加することはできま
せんか?
IKKIさんが書いたような正規表現置換でもいいのですが、マクロごとに書くと、とき
どき、メタ文字の抜けがあったりしますので。

[ ]
RE:07601 \Q〜\E 内にある \f という文字No.07603
IKKI さん 15/06/03 03:16
 
としひろさん、こんばんは。

しばらくお返事できませんでしたが、当初の方針を変えずに解決したようで(しそう
で?)何よりです。

以下は、としひろさんの「聞きたい答え」とは違いそうなので、独り言です。

http://sourceforge.net/projects/unxutils/
ここから sort.exe と diff.exe を入手し、下記マクロと同じフォルダに置いて実行
したところ、10万行のファイル2個(各6MB、全行が異なる)の差分を取る作業が5.7
秒前後で完了しました。
前後でどのような処理をしているのかわかりませんが、わずか数万行のファイルの比
較に3分も5分もかけるのは…何というか、大変もったいないことだと思います。

$file1 = "1.txt";
$file2 = "2.txt";
$file3 = "diff.txt";
runex "sort.exe -u \"" + $file1 + "\" -o \"tmp-" + $file1 + "\"", 1, 0, "",
0, "", 0, "", 1, "", 0, 0, 0;
runex "sort.exe -u \"" + $file2 + "\" -o \"tmp-" + $file2 + "\"", 1, 0, "",
0, "", 0, "", 1, "", 0, 0, 0;
runex "diff.exe -i \"tmp-" + $file1 + "\" \"tmp-" + $file2 + "\"", 1, 0, "",
 2, $file3, 0, "", 1, "", 0, 0, 0;

ご健闘をお祈り申し上げます。

[ ]
RE:07602 \Q〜\E 内にある \fという文字列No.07604
秀丸担当 さん 15/06/03 15:52
 

>\fができるようになったとしても\Eができない問題が依然として残るので、
>いっそのことマクロにPerlのquotemeta関数に相当する関数を追加することはできま
>せんか?

quotemeta関数があったら書くのも楽になると思います。
内部処理用にエスケープする関数もあったりしたので、対応しようと思います。

[ ]
RE:07604 \Q〜\E 内にある \fという文字列No.07605
IKKI さん 15/06/03 16:17
 
>quotemeta関数があったら書くのも楽になると思います。
>内部処理用にエスケープする関数もあったりしたので、対応しようと思います。

せっかく作るのでしたら、なるべく短い名前でお願いしたいです。 q() とか。

[ ]
RE:07605 \Q〜\E 内にある \fという文字列No.07606
IKKI さん 15/06/04 00:25
 
すみません、ちょっと口を滑らせた感があります。標準の関数名があんまり短いのも
善し悪しですよね…。
というわけで、他の言語がどうなっているのか調べてみました。

 .NET: Regex.Escape()
 Ruby: Regexp.escape()
 Python: re.escape()
 Scala: Regex.quote(), Regex quoteReplacement()
 Java: Pattern.quote(), Matcher.quoteReplacement()
 Perl: quotemeta()
 PHP: quotemeta(), preg_quote()
 JavaScript: 該当なし  cf. escapeHTML()

Java と Scala は検索パターン用とは別に置換パターン用のエスケープ関数が用意さ
れていますね。
秀丸でも、検索用に ()[]{}^$.*+?|\ をエスケープする関数と、置換用に \ だけを
エスケープする関数が必要になると思います。
escape() だと escape 文と混同しそうなので…

 quote($text, 1); //=> ()[]{}^$.*+?|\ をエスケープ
 quote($text, 0); //=> \ をエスケープ

…こんな感じでどうでしょうか。

[ ]
RE:07606 \Q〜\E 内にある \fという文字列No.07607
IKKI さん 15/06/04 00:53
 
あと、複数行の正規表現検索で期待通りの結果が得られるように、改行コードを \n
に置き換える処理もエスケープと同時に行うべきだと思いました。
…と思いましたが、実験してみたところ、正規表現が生の改行コードを含む場合も、
\n を含む場合と同様に、その数+1行までヒットするようです。
そうであれば、改行コードを \n に置き換える処理は要らないですね。

もしかして、ヘルプの
> 検索元文字列の中に「\n」がいくつ含まれているかを計算し、その数+1の行まで検
>索でヒット可能にします。
この記述は、正しくは
> 検索元文字列の中に「\n」と改行コードがいくつ含まれているかを計算し、その数
>+1の行まで検索でヒット可能にします。
なのではないでしょうか?

[ ]
RE:07606 \Q〜\E 内にある \fという文字列No.07608
colder さん 15/06/04 01:25
 
colderです。
IKKIさん。
置換用に\だけをエスケープする関数は本当に必要ですか?
現状、置換文字列の\以外の文字が\でエスケープされていても単純に無視されるよう
です。
厳密なことを言えば必要かもしれませんが、実用上は必要ないような気もします。

[ ]
RE:07608 \Q〜\E 内にある \fという文字列No.07609
IKKI さん 15/06/04 01:43
 
colderさん、こんばんは。

エスケープ関数の主な使いどころは、マクロで任意の(外部から来る、マクロ作者が
制御できない)置換文字列を扱う場面だと思っています。
たとえば、ユーザーが選択した文字列を取り込んで、それを置換文字列(の一部)と
して使うような場合です。
私が作ったことのあるマクロで言えば、置換ダイアログを自作のダイアログで代替す
るマクロなどが典型例です。
ユーザーに「バックスラッシュは選択しないでください」とは言えないので、どうし
てもマクロ側でエスケープ処理が必要になります。

もちろん、\ だけをエスケープする関数がなくても

 $$srcptn = quote($$1);
 $$rplptn = dllfuncstr("ReplaceRegular", "[()\\[\\]{}^$.*+?|\\\\]", $$1, 0,
"\\\\\\0", 2);

とすれば済む話ですが、せっかく quote() を作ったのに何だかなぁ…と、個人的に
は思います。


[ ]
RE:07609 \Q〜\E 内にある \fという文字列No.07610
IKKI さん 15/06/04 01:45
 
ん、まちがえました。こうですね。

 $$srcptn = quote($$1);
 $$rplptn = dllfuncstr("ReplaceRegular", "\\\\", $$1, 0, "\\\\\\0", 2);

[ ]
RE:07609 \Q〜\E 内にある \fという文字列No.07611
colder さん 15/06/04 01:59
 
>もちろん、\ だけをエスケープする関数がなくても
>
> $$srcptn = quote($$1);
> $$rplptn = dllfuncstr("ReplaceRegular", "[()\\[\\]{}^$.*+?|\\\\]", $$1, 0,
> "\\\\\\0", 2);
>
あ、いやそうじゃなくて、置換用の文字列も
$$rplptn = quote($$1);
でエスケープしちゃって$[].*?なんかもエスケープされているけど気にせず使えばい
いじゃないってことです。

[ ]
RE:07611 \Q〜\E 内にある \fという文字列No.07612
秀丸担当 さん 15/06/04 11:56
 

関数名についてですが、そのままquotemetaという名前にしようかと思っていま
したが、議論がありそうで、すぐに確定してしまうと後に響くので、次のβはい
ったん保留にして話がまとまってから決めようと思います。

IKKIさんの調べていただいたものでは「quote」や「escape」という単純な名前
の場合はRegexというクラスのメンバだったり、対象が判別できますが、グロー
バルな名前空間においては、PerlやPHPの例にあるように、quotemetaという対象
が何であるかわかるような傾向があるように思います。
それにならうとしたら、やはりquotemetaという名前が一般的という気がします。

\だけをエスケープするのは、もし必要性があれば検討しますが、colderさんの
言われるように\だけじゃなくても問題にならないのであればいいという気がし
ます。

[ ]
RE:07612 \Q〜\E 内にある \fという文字列No.07613
IKKI さん 15/06/06 00:43
 
秀丸担当さん、こんばんは。
しばらくお返事できず失礼しました。

関数名については、もとより秀丸担当さんの一存で決めていただくことに異存ありま
せん。

私が「quote(文字列, 引数) でどうでしょう」と申し上げた理由は、

 quote($text, 0); //=> \ をエスケープ
 quote($text, 1); //=> '\ をエスケープ
 quote($text, 2); //=> "\ をエスケープ
 quote($text, 3); //=> ()[]{}^$.*+?|\ をエスケープ

みたいな感じで、使用頻度の高いものをある程度カバーできたらいいんじゃないか
(いずれ要望が出て、そうする結末になるんじゃないか)と思ったからです。

というのも、今回のグローバル名前空間への関数追加はかなり例外的措置な感じがし
ています。
機能分担という観点では、本来メタ文字のエスケープ機能は本来正規表現 DLL に搭
載されるべき機能で、

 dllfuncstr("QUOTEMETA", $text);

とでもするべきものです
また、「文字列変換系機能は変換モジュールに外出しする」という方針に従えば、

 filter("", "QuoteMeta", "", $text);

とでもするべきものです。
そのどちらでもなく、あえて秀丸本体のグローバル名前空間に関数を追加するという
判断からは、使用頻度の高い機能を使いやすく提供しようという意志を感じます。

ところで、Perl や PHP の quotemeta は悪い命名だと思います。
メタ文字というのは正規表現に限った概念ではなくて、例えばシェルのメタ文字をエ
スケープする関数がもしあれば、それが quotemeta という名前であっても違和感は
ありません。
グローバル名前空間で処理対象を明確にしたいのであれば、

 quote_regexp($text);

とでもするべきです。

今回追加する関数は文字列から正規表現を組み立てるときに使うもので、1行内に複
数個出現することが想定されます。
ところが、括弧を含めて14文字の関数となると、それが1行に3個も4個もあったら
ソースが読みにくい。
同様の例として、Web アプリで HTML のメタ文字をエスケープする関数は通例 h()
と命名しますよね。
それと同じ感覚で、 q() とか qr() という名前だったらソースの可読性を損なわず、
使用頻度の高い機能を使いやすく提供するという目的に適うと思いました。

以上が hidesoft.4:07605 の発言の時点で考えていたことです。
# 考えるのは十数秒でも文章にすると長いですね…
いろいろ考えすぎて取り越し苦労っぽいことは自分でもわかっています。
最終的には秀丸担当さんがサクッと決めることですし、その決定に異存を唱えるもの
ではありません。

よろしくお願いいたします。

[ ]
RE:07613 \Q〜\E 内にある \fという文字列No.07614
IKKI さん 15/06/06 00:54
 
あ、一点抜けてました。
「グローバル名前空間で q() とか quote() とかいう名前だと処理対象が不明確」と
いうのは仰る通りです。
その曖昧さを逆手にとって、複数の処理対象をサポート(引数で切替え)できる余地
を残しておけばいいのでは?
というのが、hidesoft.4:07606 の発言の時点で考えていたことで、それが直前の発
言の冒頭につながります。

お手間を取らせてしまってすみません。m(_ _)m

[ ]
RE:07611 \Q〜\E 内にある \fという文字列No.07615
IKKI さん 15/06/06 01:03
 
>あ、いやそうじゃなくて、置換用の文字列も
>$$rplptn = quote($$1);
>でエスケープしちゃって$[].*?なんかもエスケープされているけど気にせず使えば
>いいじゃないってことです。
おお! この考えはありませんでした。
たしかに、\だけをエスケープする関数は *置換文字列用としては* 必要ないですね。

それはそれとして、
\だけをエスケープする関数は *用途を限定せず* あればあったで大変便利なものだ
と思います。

[ ]
RE:07614 \Q〜\E 内にある \fという文字列No.07616
秀丸担当 さん 15/06/08 08:51
 

確かに現時点で1つだけだとしても、余地を残しておくのはいいと思います。
一般的なケースにあてはめるとquotemeta()が適切かと思いましたが、秀丸エデ
ィタのマクロは後からパラメータを追加して動作を変えるケースもあるので、
quote()としてパラメータの余地を残しておくほうが後々のことを考えるといい
と思います。
そういう方向で考えてみようと思います。

[ ]
RE:07607 \Q〜\E 内にある \fという文字列No.07617
秀丸担当 さん 15/06/09 13:07
 

>もしかして、ヘルプの
>> 検索元文字列の中に「\n」がいくつ含まれているかを計算し、その数+1の行まで検
>>索でヒット可能にします。
>この記述は、正しくは
>> 検索元文字列の中に「\n」と改行コードがいくつ含まれているかを計算し、その数
>>+1の行まで検索でヒット可能にします。
>なのではないでしょうか?

この件について遅れてすみません。
調べてみたところ、V8.00で複数行の検索ダイアログに対応してから、改行コー
ドそのものについても幾つ含まれているかを計算していました。
ヘルプは後者のほうが正しいということになるので修正させていただきます。

[ ]
RE:07616 \Q〜\E 内にある \fという文字列No.07618
秀丸担当 さん 15/06/12 08:43
 

V8.54β8でquoteとして、現時点ではパラメータなしでしてみました。
改行コードについてはそのままにしています。
もし何らかの違う結果が必要になった場合、パラメータ追加の余地も残しておく
ようにしようと思います。

[ ]
RE:07618 \Q〜\E 内にある \fという文字列No.07619
IKKI さん 15/06/12 09:03
 
秀丸担当さん、ありがとうございました。現時点ではこれで十分と思います。

[ ]