マクロ内の繰り返しについてNo.09963
tack さん 22/10/12 17:39
 
いつもお世話になっております。
マクロで、指定文字列の並び替えを実行しようと考え以下の通りマクロを書いたので
すが、繰り返しが上手くいかず悩んでおります。

マクロの対象となる文
--------------------------------------------------------
@タイトル@@http://URL01,http://URL02,http://URL03,http://URL04,line_
height:説明01,line_height:説明02,line_height:説明03,line_height:説明0
4,http://URL11,http://URL12,http://URL13,http://URL14,http://URL
5,line_height:説明11,line_height:説明12,line_height:説明13,line_heigh
t:説明14,line_height:説明15,
--------------------------------------------------------


作成したマクロ
//---------------------------------------------------
setcompatiblemode 0x00020000;
disabledraw;
begingroupundo;//一撃で元に戻すためにグループ化

//--------------------------------------
gofiletop;
#i = 0;
while( 1 )
{
searchdown2 "@(.+?)@@", regular;
if( !result ) break; // while() ループの終了
$about[#i] = gettext( foundtopx, foundtopy, foundendx, foundendy );

searchdown2 "(?\\2)(http:)(.+?)(,)", regular;
if( !result ) { message "http:が見つかりません"; goto END; }
$voice[#i] = gettext( foundtopx, foundtopy, foundendx, foundendy );

searchdown2 "(?\\2)(line-height:)(.+?)(,)", regular;
if( !result ) { message "line-height:が見つかりません"; goto END; }
$message[#i] = gettext( foundtopx, foundtopy, foundendx, foundendy );

#i = #i + 1;
}

#data_cnt = #i; // テキストデータの総数を格納

gofileend;
#i = 0;
while( #i < #data_cnt )
{
//「,」を区切り文字としてデータを分割し配列に格納 ※3
#c1 = split( $a, $voice[#i], "," );
#c2 = split( $p, $message[#i], "," );
if( #c1 != #c2 )
 {
message "データ個数が違います";
goto END;
 }

// 見出しを追加
$s = "\n●DATA" + str( #i + 1 ) + "\n";
//「@タイトル@@」の整形
$s = $s + $about[#i] + "\n";

#j = 0;
while( #j < #c1 )
 {

// データの並び替え
$s = $s + "\"" + $a[#j] + "\"\n\"" + $p[#j] + "\"\n";
#j = #j + 1;
 }


// データの書き込み
insert $s;

#i = #i + 1;
}
END:
//--------------------------------------
endgroupundo;
enabledraw;
endgroupundo;
//---------------------------------------------------


結果
--------------------------------------------------------
@タイトル@@http://URL01,http://URL02,http://URL03,http://URL04,line_
height:説明01,line_height:説明02,line_height:説明03,line_height:説明0
4,http://URL11,http://URL12,http://URL13,http://URL14,http://URL1
5,line_height:説明11,line_height:説明12,line_height:説明13,line_heigh
t:説明14,line_height:説明15,
@タイトル@@
"//URL01"
"説明01"
--------------------------------------------------------


となります。マクロの結果の理想は
@タイトル@@
"//URL01"
"説明01"
"//URL02"
"説明02"
"//URL03"
"説明03"
"//URL04"
"説明04"
"//URL11"
"説明11"
"//URL12"
"説明12"
"//URL13"
"説明13"
"//URL14"
"説明14"
"//URL15"
"説明15"

となることですが、
今のマクロはサンプルで言えば、9個のデータ個数を格納、書き込みして欲しいとこ
ろを1回のみで終わってしまいます。

http:から始まる項目、line_height:から始まる項目は必ず , で区切られているた
め、先に改行処理を行ってからでも問題ありません。
また並び替え元の文は最終的に削除する予定ですが、並び替えが上手く動作してから
削除する予定です。

アドバイスやもっと綺麗なマクロ表記があれば、ご助言いただけますでしょうか。

[ ]
RE:09963 マクロ内の繰り返しについてNo.09964
igus さん 22/10/12 20:26
 
tackさん、こんにちは。
#data_cnt=1でbreakしてしまってますね。
データ形式のフォーマットがよく分かってないのと出力のフォーマットはもうちょっ
と詰める必要があるんですが、繰り返しの処理についてはこんな感じでどうでしょう
か。

setcompatiblemode 0x00020000;
disabledraw;begingroupundo;gofiletop;
#i=0;#fa=1;#fv=1;#fm=1;
while(1){
  //searchdown2 "@(.+?)@@", regular;
  if(!result)#fa=0;
  $about[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  searchdown2 "(?\\2)(http:)(.+?)(,)", regular;
  if(!result)#fv=0;
  $voice[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  searchdown2 "(?\\2)(line_height:)(.+?)(,)", regular;
  if(!result)#fm=0;
  $message[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;
  if(#fa+#fv+#fm==0)break;
}
#data_cnt=#i; //テキストデータの総数を格納
//message str(#data_cnt);
gofileend;
#i=0;
while(#i<#data_cnt){
  //「,」を区切り文字としてデータを分割し配列に格納 ※3
  #c1 = split( $a, $voice[#i], "," );
  #c2 = split( $p, $message[#i], "," );
  if(#c1!=#c2){message "データ個数が違います";goto END;}
  // 見出しを追加
  $s="\n●DATA"+str(#i+1)+"\n";
  //「@タイトル@@」の整形
  $s=$s+$about[#i]+"\n";
  #j=0;
  while(#j<#c1){
    //データの並び替え
    $s=$s+"\""+$a[#j]+"\"\n\""+$p[#j]+"\"\n";
    #j=#j+1;
  }


  // データの書き込み
  insert $s;
  #i=#i+1;
}
END:
endgroupundo;enabledraw;endgroupundo;

[ ]
RE:09964 マクロ内の繰り返しについてNo.09966
tack さん 22/10/12 21:27
 
igus様、こんばんわ。
ご返信ありがとうございます。
なるほど、#data_cntでbreakして繰り返しが行えなくなってたんですね。

ご提示いただいたマクロを使ってみた所

出力時結果

--------------------------------------------------------
●DATA1
説明15の途中行一部\n
"URL01,"\n
"URL01,"\n
\n
●DATA2
URL01\n
"URL02,"\n
"URL02,"\n
\n
●DATA3
URL02\n
"URL03,"\n
"URL03,"\n
\n
(省略)
●DATA14
URL13\n
"URL14,"\n
"URL14,"\n
●DATA15
URL15\n
"URL15,"\n
"URL15,"\n
--------------------------------------------------------

となってしまいました。
●DATAは見出しだけの意味なので、正直1回分も不要なのですが、書き込みに全て●D
ATAが付いてしまったことと、抽出と書込みが上手くいかなくなってしまいました。
ご提案いただいた繰り返しマクロ部分を参考にもう少し考えてみます。

フォーマットはtxt形式になります。

[ ]
RE:09966 マクロ内の繰り返しについてNo.09967
igus さん 22/10/12 22:15
 
改訂版です。ちょっと完成形に近づけたかも

setcompatiblemode 0x00020000;
disabledraw;begingroupundo;
gofiletop;#i=0;
while(1){
  searchdown2 "@(.+?)@@", regular;
  if(!result)break;
  $about[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}
gofiletop;#i=0;
while(1){
  searchdown2 "(?\\2)(http:)(.+?)(,)", regular;
  if(!result)break;
  $voice[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}
gofiletop;#i=0;
while(1){
  searchdown2 "(?\\2)(line_height:)(.+?)(,)", regular;
  if(!result)break;
  $message[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}


#data_cnt=#i; //テキストデータの総数を格納
//message str(#data_cnt);
gofileend;
#i=0;
//「@タイトル@@」の整形
$s="\n"+$about[0]+"\n";
while(#i<#data_cnt){
  //「,」を区切り文字としてデータを分割し配列に格納 ※3
  #c1 = split( $a, $voice[#i], "," );
  #c2 = split( $p, $message[#i], "," );
  if(#c1!=#c2){message "データ個数が違います";goto END;}
  // 見出しを追加
  #j=0;
  while(#j<#c1){
    //データの並び替え
    $s=$s+"\""+$a[#j]+"\"\n\""+$p[#j]+"\"\n";
    #j=#j+1;
  }
  // データの書き込み
  #i=#i+1;
}
insert $s;

END:
endgroupundo;enabledraw;endgroupundo;

[ ]
RE:09967 マクロ内の繰り返しについてNo.09968
tack さん 22/10/12 22:38
 
igus様ありがとうございます。
試してみましたところ、タイトル行しか出なかったため

message str(#data_cnt);
を有効にしてみましたところ 0 と表記されたのも繰り返しが上手くいかなかった、
ということでしょうか?

[ ]
RE:09968 マクロ内の繰り返しについてNo.09969
igus さん 22/10/13 00:46
 
こちらではうまく動作してるんですが正規表現のバージョンによってはうまくまっち
しないのかな?
ちょっと正規表現の書き方を変えてみました。

setcompatiblemode 0x00020000;
disabledraw;begingroupundo;
gofiletop;#i=0;
while(1){
  searchdown2 "@(.+?)@@", regular;
  if(!result)break;
  $about[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}
gofiletop;#i=0;
while(1){
  searchdown2 "(?<=http:)(.+?)(?=,)", regular;
  if(!result)break;
  $voice[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}
gofiletop;#i=0;
while(1){
  searchdown2 "(?<=line_height:)(.+?)(?=,)", regular;
  if(!result)break;
  $message[#i]=gettext(foundtopx,foundtopy,foundendx,foundendy);
  #i=#i+1;right;
}


#data_cnt=#i; //テキストデータの総数を格納
//message str(#data_cnt);
gofileend;
#i=0;
//「@タイトル@@」の整形
$s="\n"+$about[0]+"\n";
while(#i<#data_cnt){
  //「,」を区切り文字としてデータを分割し配列に格納 ※3
  #c1 = split( $a, $voice[#i], "," );
  #c2 = split( $p, $message[#i], "," );
  if(#c1!=#c2){message "データ個数が違います";goto END;}
  // 見出しを追加
  #j=0;
  while(#j<#c1){
    //データの並び替え
    $s=$s+"\""+$a[#j]+"\"\n\""+$p[#j]+"\"\n";
    #j=#j+1;
  }
  #i=#i+1;
}
// データの書き込み
insert $s;

END:
endgroupundo;enabledraw;endgroupundo;

[ ]
RE:09969 マクロ内の繰り返しについてNo.09970
igus さん 22/10/13 00:47
 
ちなみに ruby を使って良ければこんな感じ


setcompatiblemode 0x00020000;

begingroupundo;
runsync2 "rubyw -x "+currentmacrofilename+" "+filename;
gofileend;insert "\n";insertfile "tmp.txt";
endgroupundo;

/*
#/
#! ruby

# encoding: utf-8
Encoding.default_external = 'UTF-8'

$stdout=open("tmp.txt","w")
$stderr=open("tmp.log","w")

s1,s2=open(ARGV[0]).read,""
about  =s1.scan(/@.+?@@/)
voice  =s1.scan(/(?<=http:).+?(?=,)/)
message=s1.scan(/(?<=line_height:).+?(?=,)/)
about.each{|e| s2+=e.to_s+"\n"}
voice.each_with_index{|e,i| s2+=%Q|"#{e}"\n"#{message[i]}"\n|}
puts s2
__END__
*/

[ ]
RE:09969 マクロ内の繰り返しについてNo.09971
tack さん 22/10/13 00:55
 
igus様度々のアドバイスありがとうございます。
もう少し見てみた所、line-heightのところが、line_heightになっていました。
修正してみた所、今の内容も、先の内容も正しく動作いたしました。

どちらの内容ももう少し自分で考えてみて理解に努めようと思います。
お手を煩わせてしまい申し訳ありませんでした。
ご助言ありがとうございます!

[ ]