hmjre.dllの不可解な動作No.07164
colder さん 12/05/21 14:24
 
colderです
hmjre.dllがいくつか不可解な動作をすることがあります
現在は、正規表現を問題が起こらないように書き換えて対処していますので実害はな
いですが一応報告しておきます

・マクロ用の関数ReplaceRegularで置換が多すぎることがある
  例
    $s = dllfuncstr("ReplaceRegular","\\<.","foo bar",0,"",1);
・前方不一致指定が無視?されることがある
  例
    検索文字列「(?<!#)(#)(?!\1)」
    検索対象「##foo」
    で後ろの#にヒットする
・「\S{1}(?=\s)」がユニコード文字にヒットしない
・マッチしていない部分にある括弧に対応する後方参照にゴミが入っていることがある
  例
    検索文字列「foo (.*)(?:A=(\d+);(.*)B=(\d+);|B=(\d+);(.*)A=(\d+);)(.*) bar」
 置換文字列「foo A=\2\7; B=\4\5; \1\3\6\8 bar」
    検索対象
 afa foo D=888;B=456;C=777;A=123;E=999; bar gsfgs
 afa foo C=666;A=012;E=888;B=345;D=777; bar gsfgs

環境 win7+秀丸v8.20β20+hmjre.dll v3.41

[ ]
RE:07164 hmjre.dllの不可解な動作No.07168
秀まるお さん 12/05/21 18:03
 
 毎度お手数かけてすみません。&バグ情報ありがとうございます。

> ・マクロ用の関数ReplaceRegularで置換が多すぎることがある
>   例
>     $s = dllfuncstr("ReplaceRegular","\\<.","foo bar",0,"",1);

 これは、一応、秀丸エディタ上で全置換した場合も同じ結果になったので、仕
様ってことになると思います。

 文字列を連続置換する場合、置換で文字列を置き換えた後の次の検索開始位置
は、その置き換えた文字列の直後からになるので、そうすると、「foo」の3文
字全部に順番にヒットしてしまって、結果として空白以外の文字が全部削除され
てしまうようです。

> ・前方不一致指定が無視?されることがある
>   例
>     検索文字列「(?<!#)(#)(?!\1)」
>     検索対象「##foo」
>     で後ろの#にヒットする

 テストしてみたら再現出来ました。前方不一致指定とタグ付き正規表現が
セットになるとだめでした。さっそく修正させていただきます。




> ・「\S{1}(?=\s)」がユニコード文字にヒットしない

 これまたテストしたら再現出来ました。\S{1}のヒットする長さが最高で2
バイトまでだと仮定して高速化する、古い処理が残ってしまってました。
(ユニコード文字は内部的には4バイトになってまして)

 これまたさっそく修正させていただきます。


> ・マッチしていない部分にある括弧に対応する後方参照にゴミが入っていることがあ
> る

 現象自体は確認出来ました。ヒットしなかったはずタグが、ヒットするかどう
かテストした時の残骸を返してしまってるようです。

 詳しく調べてまたお返事させていただきます。

[ ]
RE:07168 hmjre.dllの不可解な動作No.07169
colder さん 12/05/21 18:27
 
>> ・マクロ用の関数ReplaceRegularで置換が多すぎることがある
>>   例
>>     $s = dllfuncstr("ReplaceRegular","\\<.","foo bar",0,"",1);
>
> これは、一応、秀丸エディタ上で全置換した場合も同じ結果になったので、仕
>様ってことになると思います。

あっ、本当ですね。
失礼しました。
これが、単語先頭じゃなく行先頭だと秀丸エディタ上と全置換した場合と異なる結果
になります。
    $s = dllfuncstr("ReplaceRegular","^.","foo bar a",0,"",1);

検索文字列が^. だと行先頭で1回だけマッチし、\<.だと単語先頭のマッチが繰り返
し行なわれて、単語全体が削除されるのは個人的にはかなりおかしな気がします。

[ ]
RE:07169 hmjre.dllの不可解な動作No.07170
秀まるお さん 12/05/21 22:30
 
> ・マッチしていない部分にある括弧に対応する後方参照にゴミが入っていることがあ

 これは、なんとか対応出来ました。

 タグ付き正規表現関係のバグでした。バグというか、ヒットしなかったタグが
参照されるってことが想定外になってました。ちゃんと、ヒットしなかった分は
ゼロ文字を返すように修正させていただきます。


> これが、単語先頭じゃなく行先頭だと秀丸エディタ上と全置換した場合と異なる結果
> になります。
>     $s = dllfuncstr("ReplaceRegular","^.","foo bar a",0,"",1);

 秀丸エディタで試してみたら、たしかに結果が異なっていて、ソースコードを
調べてみたら、検索文字列の先頭が「^」の場合に限って特別な処理をしていま
した。

 検索文字列の先頭が「^」で、置換した文字列の長さが0の場合、次の置換文
字列は1文字右に移動してからって処理が入っていました。

 ちなみに秀丸エディタの場合でも、全置換じゃなくて、置換コマンドを1回ず
つ実行した場合はReplaceRegular関数と同じに結果になるようではあります。

 実は秀丸エディタ側の全置換では、他にもいくつか例外的な処理があるようで
す。

 完全に同じにするのはちょっと難しいかもしれないですが、出来る限り同じ結
果になるように修正してみます。

[ ]
RE:07170 hmjre.dllの不可解な動作No.07185
colder さん 12/05/25 14:45
 
修正ありがとうございます
hmjre.dll v3.42でほぼ修正されているのを確認しました。
ただ、1ヶ所修正が不完全のようです。

>> ・「\S{1}(?=\s)」がユニコード文字にヒットしない

> これまたテストしたら再現出来ました。\S{1}のヒットする長さが最高で2
>バイトまでだと仮定して高速化する、古い処理が残ってしまってました。
>(ユニコード文字は内部的には4バイトになってまして)

サロゲートペアが考慮されていないようです。

[ ]
RE:07185 hmjre.dllの不可解な動作No.07187
秀まるお さん 12/05/25 15:10
 
 サロゲートペアのことまで考えが至りませんでした。これまた修正させていた
だきます。

 しかし、colderさんて、どうしてこんなにうまくバグを見つけられるのか、僕
が言うのも変な話ですが、なんかすごい気がします。

[ ]