SORTして同じ行のものを削除する方法No.14632
john_j_rambo さん 03/05/11 16:27
 
またお世話になります。john_j_ramboです。
…こちらは早々に的確な回答を頂けるので大変ありがたく
 思っています。

数千行あるテキストデータで、行が同じ内容のものがある場合
1行だけ残して整理したいのですが、何か方法はありますか?

例:
/aaa/bbb/ccc
/ddd/eee/fff
/aaa/bbb/ccc
/aaa/bbb/ccc
/ddd/eee/fff

    ↓

/aaa/bbb/ccc
/ddd/eee/fff


ライブラリに置いてあるマクロで、上記の動作をするマクロが
あるのですが1行ずつyes/noを聞いてくるため数千行あると
辛いです。。。
このマクロをいじってみようと思ったのですがうまくいかなかったので
こちらで相談させて頂きます。

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


[ ]
RE:14632 SORTして同じ行のものを削除するNo.14633
山紫水明 さん 03/05/11 18:35
 
 john_j_ramboさん,こんにちは。

》数千行あるテキストデータで、行が同じ内容のものがある場合
》1行だけ残して整理したいのですが、何か方法はありますか?

 以前に作ったものですが,お役にたてば。

//------- 行単一化.Mac ----------------------------------------//
$sb = searchbuffer;
#so = searchoption;
disabledraw;
gofiletop;
while( code != eof ) {
#topx = x; #topy = y;
golineend2;
#endx = x; #endy = y;
    $s = gettext( #topx, #topy, #endx, #endy );
    if( $s == "" ) {
        down;
        continue;
    }
    movetolineno 1, lineno + 1;
    #y = lineno;
    beginsel;
    gofileend;
    replaceallfast $s, "", inselect;
    #c = #c + result;
    movetolineno 1, #y;
}
replaceallfast "^\\n", "",regular;
enabledraw;
message str( #c ) + " 行削除しました。";    //必要なければ消す。
setsearch $sb, #so;
endmacro;
//------------------------------------------------------//

     では, (^^)/~
                                        山紫水明

[ ]
RE:14633 SORTして同じ行のものを削除するNo.14638
john_j_rambo さん 03/05/13 09:01
 
山紫水明 さん ありがとうございます。

お返事遅くなりました。

実行してみたのですが、消えて欲しくないところまで
消えてしまいます。

例 ****************

sakura/ume/momo
sakura/ume/momo
sakura
sakura/ume/momo
sakura/yama
sakura/kawa
sakura/umi

実行結果

sakura/ume/momo
sakura
/yama
/kawa
/umi

期待する結果

sakura
sakura/ume/momo
sakura/yama
sakura/kawa
sakura/umi

*******************

これは仕方ないのでしょうか?


それと、データが数万行になってしまいました。。。
マシンスペックにもよると思いますが、実行されているのかどうか
わからない画面状況です。大量行数でも大丈夫でしょうか?

よろしくお願いします。



[ ]
RE:14638 SORTして同じ行のものを削除するNo.14640
ENCODINGSHIFTJIS さん 03/05/13 09:30
 
>これは仕方ないのでしょうか?

はい、要求仕様に「後優先でレコードを残す」明示してないためです。
頭sakura の消失は 行全体でマッチさせていないため(すぐわかります)
算法(アルゴリズム)は計算量オーダー O(2) ですから
万行では千行の100倍の時間がかかります。
 

[ ]
RE:14640 SORTして同じ行のものを削除するNo.14641
アルビレオ さん 03/05/13 10:48
 
アルビレオです。

>>これは仕方ないのでしょうか?
>
>はい、要求仕様に「後優先でレコードを残す」明示してないためです。
>頭sakura の消失は 行全体でマッチさせていないため(すぐわかります)
>算法(アルゴリズム)は計算量オーダー O(2) ですから
>万行では千行の100倍の時間がかかります。

さすがにこの説明ではとってもわかりにくいと思うので…

'sakura'だけの行から検索したときに'sakura'を含んでいる行はすべてひっか
かって'sakura'の部分だけを削除してしまいます。
行全体が一致しているかどうかを調べるには正規表現で'^sakura$'とすればいい
わけですが、検索文字列に.*+?()[]^$などの特別な意味を持つ文字が含まれてい
ると正しく動作しません。

ついでに指摘しておくと、山紫水明さんのマクロではソートしてくれないという
問題もあります。(これについては表題のみで本文中に「ソートして」というこ
とを書き忘れたのがまずかったかなと)

対策がないわけではないですが、数万行ものデータとなると秀丸のマクロで処理
するくらいならテキスト処理用のプログラムを使ったほうが現実的です。
具体的には

sort 入力ファイル名 | uniq > 出力ファイル名

でいいのですが、sortはwindowsの標準コマンドとして存在しますがuniqコマン
ドはwindowsには標準では入っていません。
MS-DOS用(ロングファイル名に非対応)でよければvectorなどで見つかります。
win32用でコマンドプロンプトから直接実行できるものは
http://www.fred.net/tfelix/supasoft/wuup.htm
にあるwuup100.zipぐらいでしょうか。
↓こういうものもありました。
http://www.vector.co.jp/soft/win95/util/se225740.html

非常に大きなファイルを加工したり複数のファイルを一括処理する場合はマクロ
を使うよりテキストフィルタ系のプログラムを使う方が早くて楽なことが多いで
す。(場合によってはAWKやPerlを使うともっと楽ができます)
上手に使い分けてください。

[ ]
RE:14641 SORTして同じ行のものを削除するNo.14645
さん 03/05/13 13:42
 
鳩です。こんにちは。

 ご要望を正確に理解していないところもあるかとも思いますが、数万行ものデー
タとなるとアルビレオさんのいわれるようにテキスト処理用のプログラムを使った
ほうがいいと思います。

 最近では使ったことがありませんが、ソート処理で非常に優秀なのはsortfだと
思います。32ビット版もあります。
http://www.vector.jp/soft/dl/win95/util/se000882.html

 また、以前秀丸マクロのソート処理をいくつか試したときには、データによって
は正しくソートしないものがいくつもありましたので、そのあたりのことも配慮さ
れた方がいいと思います。
 例に挙げられているaaaaなどが本当にアルファベットだけならいいのですが、ア
ルファベット,漢字仮名交じりなどいろいろあると、正しく結果を出さないものが
ありえます。
 数万行オーダーだと目で確認するのは不可能ですから、よけい注意が必要です。
(すべてのソート処理秀丸マクロがそうだといっているわけではありません。)


 sortfにはチュートリアルのドキュメントも付いていまして、ご要望の件は、
(tutorial.doc)
》4  ソートして uniq
》 そもそも、モーツァルトが交響曲に使った楽器編成には、どれ位のパタンがあるで
》しょうか。
》 これは、まず楽器編成(第 6 欄)でソートし、そこが同じ行(レコード)を一つにまと
》めて仕舞えば分ります。こうした手法を

》        キーの「異なり」を抽出する

》 とか、もっと簡単に UNIX 上のコマンド名をそのままに
》        uniq を掛ける

》 とか言います。uniq は MS-DOS では(パイプがタコな為に)独立で使いにくいので、
》sortf に含まれています。

あたりの話と思います。

また、アルビレオさんの
》でいいのですが、sortはwindowsの標準コマンドとして存在しますがuniqコマン
》ドはwindowsには標準では入っていません。
も、上述引用のようにsortf に含まれています。

 お試しください。

追 こういうすごいプログラムをつくる豊島正之氏というのは何をやっている人か
と長いこと思っていましたが、日本語文字コードの有名な論客なのですね。

[ ]
RE:14645 SORTして同じ行のものを削除するNo.14646
john_j_rambo さん 03/05/13 17:29
 
山紫水明さん、ENCODINGSHIFTJISさん、アルビレオさん、鳩さん
いろいろサポートありがとうございます。

確かに数万行のデータになってしまったので、ファイルを読み込むこと
自体も大変なことになっています。
皆さんのご指摘の通り、テキスト処理用のプログラムでのsortを
考えてみます。

その他、細かく教えていただきましてありがとうございました。
またわからないところがあったら書き込みますので教えてください。


[ ]
RE:14646 SORTして同じ行のものを削除するNo.14658
山紫水明 さん 03/05/14 17:11
 
 john_j_ramboさん,ENCODINGSHIFTJISさん,
 アルビレオさん,鳩さん,こんにちは。

 ちょっと会議室をのぞかないうちに,いろいろごコメントををいただいて問
題は解決されたようですね。(^^

》行全体が一致しているかどうかを調べるには正規表現で'^sakura$'とすれば
》いいわけですが、検索文字列に.*+?()[]^$などの特別な意味を持つ文字が含
》まれていると正しく動作しません。

 そうなんですよね。置換の方法を使おうとするとこれがネックになりますね。

》ついでに指摘しておくと、山紫水明さんのマクロではソートしてくれないと
》いう問題もあります。(これについては表題のみで本文中に「ソートして」
》ということを書き忘れたのがまずかったかなと)

 これも,ソートのご要望があれば改めて,と思っていました。

》対策がないわけではないですが、数万行ものデータとなると秀丸のマクロで
》処理するくらいならテキスト処理用のプログラムを使ったほうが現実的で
》す。

 これも鳩さんも指摘されているように,もっともだと思います。最初数千行
ということでしたので,マクロで何とかなるだろうと思いました。
 前のマクロはやはり欠陥があるのでいちおう修正版を書いておきます。数千
行程度ならまあ何となるかな,と。
 マクロを勝手に走らせて,その間にコーヒーでもということであれば,もう
少し多くてもかまわないかも知れませんが。

//-------- 行単一化.MAC -----------------------------------------//
//  ソートして重複行を単一に    Ver.2
#time0 = tickcount;
title "ソート中";
disabledraw;
selectall;
run "sort < con > con";
#time1 = tickcount - #time0;
title "重複行の削除";
replaceallfast "^\\n", "", regular;
disabledraw;
gofiletop;
while( code != eof ) {
    call GetLine;
    $s1 = $$return;
    movetolineno 1, lineno + 1;
    while( 1 ) {
        call GetLine;
        $s2 = $$return;
        if( $s1 == $s2 ) {
            selectline;
            delete;
        } else break;
    }
    title str(#i);
    #i = #i + 1;
}
#time2 = tickcount - #time0 - #time1;
message "ソート:" + str(#time1) + "\n削除:" + str(#time2) + " _秒";
gofiletop;
endmacro;

GetLine:
  golinetop2;
  ##topx = x; ##topy = y;
  golineend2;
  ##endx = x; ##endy = y;
  $$s = gettext( ##topx, ##topy, ##endx, ##endy );
  return $$s;
//------------------------------------------------------//

     では, (^^)/~
                                        山紫水明

[ ]