行を跨いだデータを抽出する方法No.26305
motoak さん 09/03/05 15:44
 
秀丸エディタで、xml のタグの付いた、

<aaa> …… </aaa>
<bbb> …… </bbb>
<ccc> …… </ccc>
……
<aaa> …… </aaa>
<bbb> …… </bbb>
<ccc> …… </ccc>
<ddd> …… </ddd>
……
<aaa> …… </aaa>
<bbb> …… </bbb>
<ccc> …… </ccc>
……

のようなデータ(ファイル)の中から、<ddd> …… </ddd> を含む複数の <aaa> …
… </aaa> から <ddd> …… </ddd> までを抽出して集めたく、類似の例がないか探
したのですが、見つけられませんでした。
マクロで出来そうに思い調べてはみたのですが、マクロがなかなか理解できず、どな
たかにマクロをお願いできればなどと虫の良いことを考え書き込ませていただきまし
た。
お願いできますでしょうか?

※ </aaa> </bbb> </ccc> </ddd> の後ろは改行されています。
※ <ddd> …… </ddd> を含む物は複数個有ります。

新しいファイルを作る →  <ddd> を見つけてそのすぐ前の <aaa> にもどり、<aaa>
から </ddd> を選択してコピーし、新しいファイルにペースト。この作業を下の方向
に繰り返すマクロを書けばよいように思うのですが、よくわからないのです。よろし
くお願いいたします。

[ ]
RE:26305 行を跨いだデータを抽出する方法No.26306
秀丸担当 さん 09/03/05 16:18
 

キー操作の記録を使うと、マクロの知識が無くても簡単なマクロであれば作るこ
とができます。
例えば、以下のような操作をします。

・キー操作の記録開始(標準でShift+F1)
・<aaa>や<ddd>を検索したり、範囲選択をする操作をする
・範囲選択したら、[編集]→[追加コピー]をする
・キー操作の記録終了(標準でShift+F1)

としておくと、次からは、キー操作の再生(標準でShift+F2)をするだけで、記
録した一連の動作をまとめて行うことができます。

[マクロ]→[キー操作の保存...]をすると、記録した内容をマクロとして保存す
ることができます。

ただ、記録できるのは編集に関わる操作だけで、「新規作成」などはできません。
もしやるとしたら、マクロ化して修正する必要があります。
あと、自動的にループして検索に失敗したら終わるというようなことをするとし
たら、これもマクロ化して修正する必要があります。
マクロ化してみて、そのマクロファイルを開いてみるとわかりやすいかもしれま
せん。

ご要望と完全に一致するものではないかもしれないですが、こういった要領でク
リップボードに追加していくという操作であれば簡単にできるかもしれないです
が、どうでしょうか。

[ ]
RE:26306 行を跨いだデータを抽出する方法No.26307
motoak さん 09/03/05 16:45
 
>・<aaa>や<ddd>を検索したり、範囲選択をする操作をする

すみません。<aaa> から </ddd> を検索して範囲選択するにはどうすればよいのでし
ょうか?
範囲選択をはじめてから検索をすると範囲選択が消えてしまうのですが。

[ ]
RE:26307 行を跨いだデータを抽出する方法No.26308
motoak さん 09/03/05 16:48
 
あ、もうひとつすみません。

抽出するデータが場合によっては100組(助数詞は組でよいのでしょうか)を超える
ことも有りますので、マクロで一括して出来ればありがたいのですが。
m(_ _)m

[ ]
RE:26308 行を跨いだデータを抽出する方法No.26309
秀丸担当 さん 09/03/05 17:11
 

>すみません。<aaa> から </ddd> を検索して範囲選択するにはどうすればよいのでし
>ょうか?
>範囲選択をはじめてから検索をすると範囲選択が消えてしまうのですが。

標準のキー割り当てでShift+F6の、「選択開始」コマンドを使うといいと思いま
す。

>抽出するデータが場合によっては100組(助数詞は組でよいのでしょうか)を超える
>ことも有りますので、マクロで一括して出来ればありがたいのですが。

ループさせて、検索に失敗したら終わらせる、ということは簡単にできます。
でもおそらく条件を満たすものは以下の方法では難しいかもしれません。
例えば以下のようにします。

出来上がったマクロを、
  while(1) {
   ...
  }
で囲うと、ループさせることができます。

マクロ化してみると分かると思いますが、例えば検索だけした場合は以下のよう
な感じで記録されていると思います。

  setcompatiblemode 0x0F;
  searchdown "aaa" , hilight;
  if( ! result )  beep;

最初の setcompatiblemode は約束事のようなもので無視してもかまいません。
失敗したというビープ音という意味で、beep;の代わりに endmacro;とすると、
検索失敗で終わらせることができます。
例えば、検索だけループして、検索失敗したら終わらせるには以下のようにしま
す。

  while(1) {
    searchdown "aaa" , hilight;
    if( ! result )  endmacro;
  }



最初に言われているような<ddd>が他にもあったりすると、この方法では不足か
もしれないです。
<aaa>と<ddd>がたくさんあって、どれが該当するものでどれが除外するものか、
はっきりとした条件があるのであれば、何らかの方法があるかもしれないですが。

[ ]
RE:26308 行を跨いだデータを抽出する方法No.26310
Iranoan さん 09/03/05 17:20
 
 motoak さん今日は、Iranoan です。
 念の為お断りしておくと、開発者とは何の関わりも無い単なる一ユーザです。
> すみません。<aaa> から </ddd> を検索して範囲選択するにはどうすればよいのでし
> ょうか?
 <aaa> を検索してから、「選択開始」(beginsel 文) を使ってから </ddd>
を使えばよいです。</ddd> 自身を選択含むかは、設定によって変わるかもし
れませんので、</ddd> 検索後
moveto foundendx, foundendy;
に当たることをする必要があるかもしれません。
> 抽出するデータが場合によっては100組(助数詞は組でよいのでしょうか)を超える
> ことも有りますので、マクロで一括して出来ればありがたいのですが。
については、その部分も含めて全体を
> キー操作の記録を使う
で良いでしょう。

 サンプル・マクロを書こうかと思ったのですが、
> 新しいファイルを作る → <ddd> を見つけてそのすぐ前の <aaa> にもどり、<aaa>
> から </ddd> を選択してコピーし、新しいファイルにペースト。
の意味がよく解りませんでした。取り敢えず、「<ddd> を見つけてそのすぐ前
の <aaa> にもどり、<aaa> から </ddd> を選択」の部分だけ、憶測で書いて
みました。
//------------------------------------------------------------
searchdown "<ddd>";
#x = x;
#y = y;
if( !result )goto Error;//見つからなければ終了
searchup "<aaa>";
if( !result )goto Error;//間に <ddd> や </ddd> が無いかの確認は省略
beginsel;
searchdown "</ddd>";
if( (!result)
  || y < #y || ( y == #y && #x > x ) //</ddd> が <ddd> より後ろにあるか?
  )goto Error;
moveto foundendx, foundendy;
endsel;
endmacro;

Error:
  escape;

[ ]
RE:26309 行を跨いだデータを抽出する方法No.26314
motoak さん 09/03/05 20:41
 
>出来上がったマクロを、
>  while(1) {
>   ...
>  }
>で囲うと、ループさせることができます。

キー操作を記録したものに、上記の「while ……」を付けて、

---------------------------
while (1) {
 searchdown "<ddd>" , casesense, hilight;
 if( ! result )  endmacro;
  escape;
 searchup "<ddd" , casesense, hilight;
 if( ! result )  beep;
 escape;
 golinetop;
 beginsel;
 searchdown "</ddd>" , casesense, hilight;
 if( ! result )  beep;
 golineend;
 appendcopy;
 golinetop;
 down;
}
---------------------------

を実行して新しいファイルを開きペーストしたところ、ほぼ希望しているのに近い結
果が得られました。

ただ、ペーストした先頭に

「 if( ! result )  endmacro;」

が入ってしまう事と、

</ddd><aaa>……

と、</ddd> と <aaa> が繋がってしまいます。

先頭に入ってしまう文字列が入らないようにして、
</ddd> と <aaa> に改行(出来れば改行を2つ)を入れるにはどうすればよいでしょ
うか?

またこのあと、新しいファイルを開いてそこにペーストまでをマクロで出来るように
したいのですが。
よろしくお願いいたします。

[ ]
RE:26310 行を跨いだデータを抽出する方法No.26315
motoak さん 09/03/05 20:47
 
Iranoan さま。
有り難うございます。

秀丸担当さまに教えて頂いた方を先にしましたところ、上記「26314 コメント」のよ
うになりました。
その形をスマートに書くとお教え頂いたようになるのでしょうか?

[ ]
RE:26314 行を跨いだデータを抽出する方法No.26316
motoak さん 09/03/05 20:59
 
>while (1) {
> searchdown "<ddd>" , casesense, hilight;
> if( ! result )  endmacro;
>  escape;
> searchup "<ddd" , casesense, hilight;
> if( ! result )  beep;

searchup "<aaa" , casesense, hilight;
if( ! result )  beep;

でした、すみません。

[ ]
RE:26314 行を跨いだデータを抽出する方法No.26317
Iranoan さん 09/03/05 21:03
 
 motoak さん今日は、Iranoan です。
 ヒントだけ書いておきますね。
> ただ、ペーストした先頭に
>
> 「 if( ! result )  endmacro;」
>
> が入ってしまう事と、
<snip>
> 先頭に入ってしまう文字列が入らないようにして、
に関しては、おそらくマクロ実行前にクリップボードに保存されていた分だと
思いますので、
setclipboard "";
の要領で、setclipboard 文を使って、最初にクリップボードの内容を初期化
しておくと良いと思います。

> </ddd> と <aaa> に改行(出来れば改行を2つ)を入れるにはどうすればよいでしょ
> うか?
については、
>  appendcopy;
とクリップボードにどんどんデータを追加しているので、
 appendcopy;
 addclipboard "\n\n";
等と、データを追加するたびに、改行を追加すれば良いかと。

> 新しいファイルを開いてそこにペーストまでをマクロで出来るように
> したい
 最後に、
newfile;
paste;
を追加だけで良いと思います。

 あと一度、ここのコマンドをマクロ・ヘルプで確認していくと、修正がしや
すいかと。

[ ]
RE:26314 行を跨いだデータを抽出する方法No.26318
秀丸担当 さん 09/03/06 09:14
 

>ただ、ペーストした先頭に
>
>「 if( ! result )  endmacro;」
>
>が入ってしまう事と、


おそらくマクロ実行前のクリップボードの内容が残っているためで、事前に手動
で空の内容をコピーしておくか、Iranoanさんの言われる通りマクロ先頭に

  setclipboard "";

としておくといいと思います。

></ddd><aaa>……
>
>と、</ddd> と <aaa> が繋がってしまいます。
>
>先頭に入ってしまう文字列が入らないようにして、
></ddd> と <aaa> に改行(出来れば改行を2つ)を入れるにはどうすればよいでしょ
>うか?

キー操作の記録を使う場合は、改行があるはずの場所で改行だけを選択して、
「追加コピー」をするといいと思います。

マクロを修正する場合は、Iranoanさんの言われる通り、

  addclipboard "\n\n";

という方法もあります。


>またこのあと、新しいファイルを開いてそこにペーストまでをマクロで出来るように
>したいのですが。
>よろしくお願いいたします。


新しいファイルを開くには、マクロの最後に、

  newfile;
  paste;

とするといいと思います。
新規作成に相当するnewfileは、キー操作の記録はできませんが、[マクロ]→[マ
クロヘルプ]より、各コマンドに相当する文がほぼ一対一で書かれているので、
参考にされるといいかもしれません。

ただ、beep; を endmacro; に修正された部分は、endmacroだとマクロが終わっ
てしまうので、break; にしないといけないと思います。
break;にすると、while(1){}のループをから外に出るという意味になります。

例:
  while(1){
    searchdown "<ddd>" , casesense, hilight;
    if( ! result )  break;
       :
       :
  }
  newfile;
  paste;

[ ]
RE:26318 行を跨いだデータを抽出する方法No.26319
motoak さん 09/03/06 12:35
 
秀丸担当さま
Iranoan さま
ありがとうございます。
作業の内容を具体的に示すことが出来ないため、また、xml についての知識が無く、
変な聞き方をしてすみませんでした。

私なりに少し調べてみました。その知識で修正させていただくと:

たとえば、1〜2万あまりの <record> という要素で括られたデータがあり、<recor
d> 要素の中に <ID> <hoge1> <hoge2> …… <hosoku> <fuga1> <fuga2> ……、など
の各要素がある(ただし <hosoku> 要素は全てにあるわけではない)、その中から <
hosoku> 要素を含むレコードの、<ID> と <hosoku> 要素を集める、というものです。

こういう書き方で伝わるでしょうか?

そこで、お二人のアドバイスを元にやってみた結果です。

-----------------------------------------------
setclipboard "";
while (1) {
 searchdown "<hosoku>" , casesense, hilight;
 if( ! result )  break;
 escape;
 searchup "<ID" , casesense, hilight;
 if( ! result )  beep;
 beginsel;
 searchdown "</ID>" , casesense, hilight;
 if( ! result )  beep;
 golineend;
 appendcopy;
 addclipboard "\n";
 searchdown "<hosoku>" , casesense, hilight;
 if( ! result )  beep;
 beginsel;
 searchdown "</hosoku>" , casesense, hilight;
 if( ! result )  beep;
 golineend;
 appendcopy;
 addclipboard "\n\n";
 golinetop;
 down;
}
newfile;
paste;
-----------------------------------------------
(「aaa」「ddd」は「ID」「hosoku」に変えました)

とすることで、希望通りの形でこれらのレコードを集めることが出来ました。

そこでマクロについてもう少し知りたいのですが、ここではキー操作の紀録を使って
マクロの形にしていますが、これをもう少しスマートなマクロにすることは出来ない
でしょうか?
これを機に少しマクロについて知っておきたいと思いましたので。
よろしくお願いいたします。

[ ]
RE:26318 行を跨いだデータを抽出する方法No.26320
motoak さん 09/03/06 12:49
 
すみません、もうひとつ。
ここで使った
appendcopy;
には、回数やバッファ(?)の大きさに制限はあるのでしょうか?

扱うデータが多くまた大きくなると場合によってはその上限をはみ出してしまうこと
もあるかもしれないと、気になりましたので。
よろしくお願いいたします。

[ ]
RE:26318 行を跨いだデータを抽出する方法No.26321
motoak さん 09/03/06 13:06
 
何度もすみません m(_ _)m

> たとえば、1〜2万あまりの <record> という要素で括られたデータが
> あり、<record> 要素の中に <ID> <hoge1> <hoge2> …… <hosoku>
> <fuga1> <fuga2> ……、などの各要素がある(ただし <hosoku> 要素は
> 全てにあるわけではない)、その中から <hosoku> 要素を含むレコード
> の、<ID> と <hosoku> 要素を集める、というものです。
> こういう書き方で伝わるでしょうか?
> そこで、お二人のアドバイスを元にやってみた結果です。

ではなく


たとえば、1〜2万あまりの <record> という要素で括られたデータがあり、<recor
d> 要素の中に <ID> <hoge1> <hoge2> …… <hosoku> <fuga1> <fuga2> ……、など
の各要素がある(ただし <hosoku> 要素は全てにあるわけではない)、その中から <
hosoku> 要素を含むレコード
の、<ID> から <hosoku> 要素を集める、というものでした。

こういう書き方で伝わるでしょうか?

そこで、お二人のアドバイスを元に
上記の「<ID> から <hosoku> 要素を集める」を「<ID> と <hosoku> 要素を集める」
として、やってみました。

とすべきでした。
ほんとうに何度もすみません。

[ ]
RE:26320 行を跨いだデータを抽出する方法No.26322
秀丸担当 さん 09/03/06 13:07
 

>たとえば、1〜2万あまりの <record> という要素で括られたデータがあり、<recor
>d> 要素の中に <ID> <hoge1> <hoge2> …… <hosoku> <fuga1> <fuga2> ……、など
>の各要素がある(ただし <hosoku> 要素は全てにあるわけではない)、その中から <
>hosoku> 要素を含むレコードの、<ID> と <hosoku> 要素を集める、というものです。
>
>こういう書き方で伝わるでしょうか?

詳しい条件ありがとうございます。
<aaa>や<ddd>が該当しないものがありそうなことが心配だったのですが、既に良
い結果が得られているのであれば、問題無いと思います。


>そこでマクロについてもう少し知りたいのですが、ここではキー操作の紀録を使って
>マクロの形にしていますが、これをもう少しスマートなマクロにすることは出来ない
>でしょうか?

マクロを本格的に作るともっと複雑になることが多いので、この状態がスマート
なような気がします。
しいて言えば、 if( ! result )  beep; が不要であれば、削除してもかまわな
いと思います。

あと1つ気になったのが、折り返しがあると、Home,End,↓キーの操作で作られ
たと思われる、golinetop, golineend, down がおかしなことになるかもしれな
いです。
折り返しが無ければ問題無いと思いますが、もしありそうな場合、[その他]→
[ファイルタイプ別の設定]→[体裁]で、折り返しを最大にしておいたほうがいい
かもしれません。
最大だと2000文字になりますが、それでも折り返しが出る場合は、折り返しを無
視した形の以下のように書き換えたほうが安全かもしれません。
golinetop; → golinetop2;
golineend; → golineend2;
down;      → movetolineno column + 1, lineno + 1;



>appendcopy;
>には、回数やバッファ(?)の大きさに制限はあるのでしょうか?

特に制限というのはありません。
メモリ不足や、貼り付けるときの秀丸エディタ自体の行数制限([その他]→[動
作環境]→[環境]→[編集可能な最大行数])になったりするまでは大丈夫かもし
れないです。もしかしたら何か別の要因で失敗する可能性もあるかもしれないで
すが。
試しに、大きなテキストを選択してみて、[編集]→[追加コピー]を繰り返してみ
ると、実際にやろうとしていることが耐えられるかどうかを試してみることがで
きると思います。

[ ]
RE:26320 行を跨いだデータを抽出する方法No.26323
秀丸担当 さん 09/03/06 13:17
 

あと、速度面でいうと、マクロ先頭に

  disabledraw;

を入れておくと描画しなくなるので高速になります。

[ ]
RE:26323 行を跨いだデータを抽出する方法No.26329
motoak さん 09/03/09 12:32
 
ありがとうございます。
全ての疑問に丁寧にお答えいただき大変感謝しております。

気がつかずに見落としそうな理論行での行頭・行末へのカーソル移動のことなど、大
変助かります。

>  disabledraw;
は、作業が一つだけの時はまだ怖くて使えませんが、複数ファイルについて行う場合
は大変ありがたいのです。

以前、前知識もなく何気なく書いて試してみた「while」文でループが止まらなくな
って escape キーでも終了させることが出来なくなり、それ以来、マクロは自分の手
には負えない、と自分でマクロについて何かすることを敬遠しておりましたが、今回
のことでかなり身近に感じることが出来るようになりました。

あまり高度なことは出来るようにはならないと思いますが、キーマクロを利用した今
回の簡単なマクロなど、もう少し積極的に試してみようと思います。

ほんとうにありがとうございました!

[ ]