重複スペースやタブ、改行を削除する方法No.06614
TAKATAKA さん 11/05/30 14:32
 
秀丸ユーザの皆さんこんにちは

TAKATAKAと申します。
秀丸のバージョンは8.04です。

どちらに質問すれば良いのか迷ったのですが、
今回はマクロ作者会議室に質問させていただきます。

現在、HTMLタグの整形をしているのですが、上手くできません。
例えば、以下のようなタグを、

<img
      border="0"     height="300" src="test/images/image.gif"           widt
h="200"    class="test1 test2">


次の指示に従って、

1.タグ<>内の改行を全て削除する(重複する場合も全て削除)
2.タグ<>内のタブを全て削除する(重複する場合も全て削除)
3.タグ<>内の重複半角スペースを半角スペース1つにする


以下のように整形したいと考えております。

<img border="0" height="300" src="test/images/image.gif" width="200" class="
test1 test2">


実際に処理しているマクロは次のとおりです。

//タグ中の改行を削除 : (<[^<>]*)\n+([^<>]*>) -> \1\2
gofiletop;
replaceall "(<[^<>]*)\n+([^<>]*>)", "\\1\\2", regular, nocasesense, ask;

//タグ中のタブを削除 : (<[^<>]*)\t+([^<>]*>) -> \1\2
gofiletop;
replaceall "(<[^<>]*)\t+([^<>]*>)", "\\1\\2", regular, nocasesense, ask;

//タグ中の重複半角スペースを半角スペース1つに変換 : (<[^<>]*)\s+([^<>]*>),
\1\2
gofiletop;
replaceall "(<[^<>]*)\s+([^<>]*>)", "\\1\\2", regular, nocasesense, ask;


●上手くいかない理由

1.パターンの中で\n+や\t+、\s+(1個以上)としているのに、重複するタブやス
ペースを一気に削除できない
(一つずつの削除になる)

2.一つのタグの中で、パターンに一致する場所が複数あるのに、
一番後ろの一致部分しか置換えされない

3.さらに以下のように3行以上のタグになると、検索に引っかからない

<img
     border="0"     height="300" src="test/images/image.gif"           width
="200"
   class="test1 test2">


上記理由の解決策をご存じの方がいらっしゃいましたら
ぜひご教授ください。
宜しくお願いいたします。

[ ]
RE:06614 重複スペースやタブ、改行を削除No.06615
秀まるお2 さん 11/05/30 18:34
 
> 3.さらに以下のように3行以上のタグになると、検索に引っかからない

 これは秀丸エディタの制限によるものですが、回避策があります。

   (?#maxlines:10)(<[^<>]*)\n+([^<>]*>)

 のように書くと、最高10行までヒットします。

 詳しくは、検索の所でヘルプを表示させると、そこに「\nを使った複数行検索
の際の制限について」というのがあるので、そこを参照してみて欲しいです。

 他の問題点についてもちょっと考えてみます。

[ ]
RE:06615 重複スペースやタブ、改行を削除No.06616
秀まるお2 さん 11/05/30 18:44
 
 置換については、まずは「ファイルタイプ別の設定・デザイン・複数行コメン
ト」の「言語」を「HTML/XML」にした上で、

 replaceallfast "\\n" , "", regular, masktag, maskonly;

 のようなことをすればいいんじないかと思います。そうすればタグの中の改行
のみすべて除去されます。

 同様の方法で\tとかも除去出来るし、複数つらなった空白を1つだけにしたり
とかも出来ると思います。

    replaceallfast " ( )+", " ", regular, masktag, maskonly;

 でいけるかと。

[ ]
RE:06616 重複スペースやタブ、改行を削除No.06617
秀まるお2 さん 11/05/30 20:23
 
 正規表現だけでなんとかやるとしたらですが…

 HTMLタグが絶対正しく書かれているという前提でなら、例えば

 replaceall "(?#maxlines:10)\\n(?=[^<]*?>)" , "" , regular;

 のように後方一致指定だけ使うやり方でもなんとかいけそうです。

[ ]
RE:06617 重複スペースやタブ、改行を削除No.06618
TAKATAKA さん 11/05/31 21:53
 
秀まるお2さんへ

こんばんはTAKATAKAです。
ご教授ありがとうございました。

masktag, maskonlyという
魔法の呪文のようなオプションがあったのですね!
これでバッチリ動きました!
ありがとうございます。

そこでもう一つだけ質問があるのですが、
よろしいでしょうか。

いよいよオリジナルのマクロ作りも佳境になりまして、
HTMLタグ加工後の最終整形を行いたいのですが、
最後のinsertの部分が上手くいきません。

やりたい事は、


<table class="10 test1" border="0" align="center" class="12 test2" height="3
00" width="200" class="15 test3">


上のようにclass属性が複数あるタグを、次のように一つにまとめたいのです。


<table class="10 test1 12 test2 15 test3" border="0" align="center" height="
300" width="200">


しかし、現状では、以下のように置き換わってしまいます。


<table class="10 test1 12 test2 15 test3" border="0" align="center" height="
300" width="200">class="10 test1" border="0" align="center" class="12 test2"
 height="300" width="200" class="15 test3">


結構いいところまで行っているのですが、
自力で解決できなくて残念です。
(多分、searchdown2とinsertの連携だと思うのですが・・・)

度々で恐縮ですが、ご教授いただけないでしょうか。
宜しくお願いいたします。

コードは以下のとおりです。
このコードは、ユーザのIKKIさんからいただいたものをアレンジして作成しました。
IKKIさんありがとうございました!

---------------------------------------------------------------------------
ここから
loaddll "hmjre.dll";
begingroupundo;

gofiletop;
searchdown2 "(?<=(<.*?))(class=\".*){2,}", regular, nocasesense, masktag, ma
skonly;

while (result) {

 $$class = "";
 $$tag = "";
 $$tag = gettext(foundtopx, foundtopy, foundendx, foundendy, true);

message "最初のtagの中身:" + $$tag;

 while (true) {

  if (dllfunc("FindRegularNoCaseSense", " class=\"(.*?)\"", $$tag, 0) < 0) {
   break;
  }

  $$value = "";
  $$value = midstr($$tag, dllfunc("GetLastMatchTagPosition", 1), dllfunc("Ge
tLastMatchTagLength", 1));

  if ($$class == "") {
   $$class = "class=\"" + $$value;
  }else{
   $$class = $$class + " " + $$value;
  }

  $$tag = dllfuncstr("ReplaceRegularNoCaseSense", " class=\"(.*?)\"", $$tag,
 0, "", 0);

 }

 message $$class + "\"" + $$tag;
 insert $$class + "\"" + $$tag;

 finddown2;
}

endgroupundo;
freedll;
---------------------------------------------------------------------------
ここまで

[ ]
RE:06618 重複スペースやタブ、改行を削除No.06619
秀まるお2 さん 11/05/31 22:23
 
 class=の後ろが必ず""で囲まれてるという前提であれば、

Loop1:
    replaceall "(?#maxlines:10)class\\s*=\\s*\"([^\"]*?)\"\\s+([^<>]*?)\\s+c
lass\\s*=\\s*\"([^\"]*?)\""
          , "class=\"\\1 \\3\" \\2"
          , regular, masktag, maskonly;
    if( result != 0 ) {
        goto Loop1;
    }

 のような処理、つまり、「class="A" ... class="B"」となってるのを
「class="A B" ...」のように置換してしまうのをヒットするだけ繰り返す、と
いうやり方でうまくいくと思います。

 (こちらでテストした限りはそれでうまく置換出来ました)

 class="A"のようになってなくて、例えばclass=A のように書かれてるとダメ
ですけども、それについては、

    gofiletop;
    searchdown2 "[a-z]+\\s*=\\s*[a-z0-9_]", regular, masktag, maskonly;
    if( result ) {
        message "ダブルクォーテーションで囲まれてないです。";
        endmacro;
    }

 のような処理で検索させて、そういう書き方をエラー扱いにしてしまったらい
いんじゃないかと思います。(または自動的に置換してやってもいいかも)

[ ]
RE:06619 重複スペースやタブ、改行を削除No.06620
TAKATAKA さん 11/06/02 10:05
 
秀まるお2さんへ

こんにちはTAKATAKAです。
最初のループ文でバッチリ対応できました!
ありがとうございます。
本当に助かりました。

[ ]