次のような内容の入ったテキストファイルがあるとします。(生物の類縁関係を表すものです)
(1:0,2:0.001336,((((3:0.002674,4:0,25:0,26:0,50:0):0.001334,5:0.005347,・・・
1:とか2:とか3:とかいう部分は生物名のラベルを意味しています。
別のテキストファイルにはタブ区切りで、
1 Kainan
2 Gobo
3 Kusimoto
・・・
というように、ラベル名の情報が入っています。
最初のファイルの1:とか2:とか3:とかの部分を、Kainan:、Gobo:、Kusimoto: とかいうふうに置き換えたいのです。
以前は手作業でやっていたのですが、あまりに不毛な作業なのでプログラムしたいと考えるようになりました。
参考になるサイトを教えていただければ幸いです。
テキストエディタは秀丸を使っています。
言語はc++をちょっとかじったくらいです。
もちろん、すぐ使えるようなマクロなどあれば大歓迎です。
皆様のお知恵を拝借したいと思います。
よろしくお願いします。
1つのフォルダに
・目的のファイル(複数可能 名前なんでも).txt
・ラベル名の情報のファイル "label.txt"
・以下を".vbs"をつけて保存したもの
を置いて、vbsファイルをダブルクリックすると、後ろに"_out.txt"のついたファイルが出来上がります。
set fso=createobject("scripting.filesystemobject") set she=createobject("wscript.shell") set labels=createobject("scripting.dictionary") set regex=new regexp regex.global=true set_label "label.txt" for each f in fso.getfolder(".").files if f.name<>"label.txt" and right(f.name,4)=".txt" then exec f.name end if next sub set_label(fname) set infile=fso.opentextfile(fname) regex.pattern="(.*)\t(.*)" do while not infile.atendofstream line=infile.readline set pair=regex.execute(line)(0) labels.add pair.submatches(0), pair.submatches(1) loop end sub sub exec(fname) set infile=fso.opentextfile(fname) set outfile=fso.createtextfile(fname & "_out.txt") regex.pattern="([0-9]+):" do while not infile.atendofstream line=infile.readline for each hit in regex.execute(line) hit=hit.submatches(0) line=replace(line, hit & ":", labels(hit) & ":") next outfile.writeline line loop end sub
秀丸ということは Windows ですね。
私としてはこの手の処理には Perl をお勧めします。
Windows なら ActivePerl でしょうか。
http://www.activestate.com/activeperl/
まずはラベル名の入ったテキストファイルを読み込んでハッシュを作り、
次に、類縁関係の入ったテキストファイルをオープンして置換すればいいと思います。
この例だけでは類縁関係のデータフォーマットがよくわかりませんが、
基本的な考え方はこれでいいと思います。
Perl はネット上に情報が多く習得しやすい上に、簡単な処理をさっと書くにもうってつけです。
データ処理が多い仕事だと、今後必ず役に立つと思うので、習得して損はないのではないでしょうか。
perlについては大学の先生にもおすすめされました。
一度挫折したのですが(インストールで(笑))、修得してみようと思います。
ありがとうございました。
やりたいことがあまり一般的ではないので、すぐに使えるものは無いと思いますよ。自分で作ったほうが手っ取り早いです。
やり方として考えられるのはる入力テキストを読み込み、別途ラベルファイルも読み込み、ラベルをつけて出力する方法ですかね。
この実現方法としては、本格的にプログラムを組むこともできますが、cygwin+シェルスクリプトなんかで作ったほうが楽だと思います。
シェルスクリプトでやるなら、実装としては、
入力ファイルを読み込んで、変数dataに入れる
ラベルファイルを読み込む
ラベルファイルを1行取り出すごとに、dataを/(,\()$num:/\1$val:/g の正規表現で置換、以下ラベルファイルの末尾まで繰り返す
最後にdataを出力する
という感じですかね。$numはラベルファイルのタブの左側の値、$valはラベルファイルのタブの右側の値を入れた変数です。
cygwinの使い方は以下で。
cygwin以外なら、pythonやrubyを使ってもいいです。大体似たようなロジックでいけますが、
その場合は正規表現ではなく構文解析して置換した方がわかりやすいプログラムになると思います。
C++はこの手の作業には面倒なので、スクリプトやスクリプト言語なんかを使ったほうがいいでしょう。
cygwinというのは聞いたことがありませんでした。勉強してみます。
ありがとうございました
1つのフォルダに
・目的のファイル(複数可能 名前なんでも).txt
・ラベル名の情報のファイル "label.txt"
・以下を".vbs"をつけて保存したもの
を置いて、vbsファイルをダブルクリックすると、後ろに"_out.txt"のついたファイルが出来上がります。
set fso=createobject("scripting.filesystemobject") set she=createobject("wscript.shell") set labels=createobject("scripting.dictionary") set regex=new regexp regex.global=true set_label "label.txt" for each f in fso.getfolder(".").files if f.name<>"label.txt" and right(f.name,4)=".txt" then exec f.name end if next sub set_label(fname) set infile=fso.opentextfile(fname) regex.pattern="(.*)\t(.*)" do while not infile.atendofstream line=infile.readline set pair=regex.execute(line)(0) labels.add pair.submatches(0), pair.submatches(1) loop end sub sub exec(fname) set infile=fso.opentextfile(fname) set outfile=fso.createtextfile(fname & "_out.txt") regex.pattern="([0-9]+):" do while not infile.atendofstream line=infile.readline for each hit in regex.execute(line) hit=hit.submatches(0) line=replace(line, hit & ":", labels(hit) & ":") next outfile.writeline line loop end sub
プログラムまで組んでいただいてありがとうございました!
出力にびっくりしました。
スクリプト言語は強力なんですね。
興味がわいてきました。勉強してみようと思います。
ありがとうございました。
ついでに質問をよろしいでしょうか。(自分でも考えてみます)
上のプログラムだと、二桁の番号がある場合に(ラベルは全部で65番まであります。これは説明すべきでした。すみませんでした)
例えば51: → 5Kushimoto:
となってしまうようです。
これを改良するのはどの部分を変えればよろしいでしょうか。
プログラムまで組んでいただいてありがとうございました!
出力にびっくりしました。
スクリプト言語は強力なんですね。
興味がわいてきました。勉強してみようと思います。
ありがとうございました。
ついでに質問をよろしいでしょうか。(自分でも考えてみます)
上のプログラムだと、二桁の番号がある場合に(ラベルは全部で65番まであります。これは説明すべきでした。すみませんでした)
例えば51: → 5Kushimoto:
となってしまうようです。
これを改良するのはどの部分を変えればよろしいでしょうか。