プロが教える店舗&オフィスのセキュリティ対策術

お世話になります。
テキストファイルの切り出し方法について教えて下さい。
現在数千万行のテキストファイルがありまして、そこからひつよな部分を切り出したいです。
切り出す部分は、特定文字列から2000行や4000行といった行数です。

たとえば
x 速度. y 速度. x-温度. y-温度.
という文字列があれば、その文字列を含み下4000行を切り出して、一番初めの物であれば
date_00001.txt
次は
data_00002.txt
といった形で保存していってほしいです。

エクセルマクロならば対応ができたのですが、行数が多すぎて、エクセルで処理できず立ち往生してしまっております。(現在は100万行程度ずつにある程度切り分けてマクロを回しておりますが、ミスが多発しております。)

rubyやpythonを動かすことは可能なのですがあまり詳しくなく、楽しいrubyを見て勉強している段階です。
すみませんが、詳しい方切り出し方及び連番ファイルの作成方法を教えて下さい。

A 回答 (7件)

エクセルのマクロを作ってみました。


元ファイルが同じフォルダにあり、出力先も同じフォルダーにしてあります。
※ フォルダを変更したい場合は「ThisWorkbook.Path」が有る行を修正して下さい。

Sub Sample()

Const 対象文字 As String = "x 速度. y 速度. x-温度. y-温度."
Const 行数 As Long = 4000
Const 元ファイル名 As String = "元データ.txt"
Const 頭 As String = "date_"
Dim 行データ As String
Dim 元 As Integer
Dim 先 As Integer
Dim 出力名 As String
Dim 連番 As Long
Dim 位置 As Long

 元 = FreeFile
 Open ThisWorkbook.Path & "\" & 元ファイル名 For Input As #元
 Do Until EOF(元)
  Line Input #元, 行データ
  If 行データ = 対象文字 Then
   連番 = 連番 + 1
   出力名 = ThisWorkbook.Path & "\" & 頭 & Format(連番, "00000") & ".txt"
   先 = FreeFile
   Open 出力名 For Output As 先
   Print #先, 行データ
   For 位置 = 2 To 行数
    Line Input #元, 行データ
    Print #先, 行データ
   Next
   Close #先
  End If
 Loop
 Close
 MsgBox ("終了しました")

End Sub
    • good
    • 0
この回答へのお礼

ありがとうございます。
なるほど、外部ファイルを読み込んでvbaとして回すときはLine Inputで一行ずつ読んでいくのですね。
勉強となりました。ありがとうございます。

お礼日時:2019/12/09 14:46

>検索対象の文字列を一緒に出力しないという方法もあるのでしょうか?


以下の個所ですが
#見出し行出力
octr = 1
outf.print line
上記を
octr = 0
#outf.print line・・・・コメントアウト
のように変えてください。
出力行が1行減るので、outctrは0にしておきます。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2019/12/10 13:01

rubyで作成しました。


----------------------------------------
# coding:WINDOWS-31J
def main()
if ARGV.count != 2
print "#{$0} 入力ファイル名 切り出し件数\n"
exit(10)
end
fname = ARGV.shift #入力ファイル名
ostr = ARGV.shift #切り出し件数
if ostr =~ /^\d+$/
ocount = ostr.to_i
else
ocount = 0
end
if ocount < 1
print "切り出し件数不正:#{ostr}\n"
exit(10)
end
find_str = 'x 速度. y 速度. x-温度. y-温度.' #検索文字列
fseq = 0 #出力ファイル番号
#入力ファイルオープン
File.open(fname) do |inf|
#最後まで読み込む
while line = inf.gets
# 検索対象の文字列が1行内に存在するなら、切り出しを行う
if line.include?(find_str)
fseq += 1
ofname = sprintf("date_%05d.txt",fseq)
#出力ファイルオープン
File.open(ofname,"w") do |outf|
#見出し行出力
octr = 1
outf.print line
#切り出し件数に達するか、入力ファイルが終わる迄繰り返す
while true
break if octr >= ocount
line = inf.gets
break if line == nil
octr += 1
outf.print line
end
end
end
end
end
end
main()
--------------------------------------------
実行方法は以下のようになります。
このスクリプト名をsample.rbとします。
コマンドプロンプトで以下のコマンドを入力します。
ruby sample.rb 入力ファイル名  切り出し件数
    • good
    • 0
この回答へのお礼

どうもありがとうございます。
rybyめちゃくちゃ早いですね。5000万行のデータを今さっき切り出してみたのですがすぐに終わって驚きました。
すみません、
検索対象の文字列を一緒に出力しないという方法もあるのでしょうか?

お礼日時:2019/12/10 11:14

ruby でオブジェクト指向っぽく実装した例



class CutoutFile
_ def initialize
_ _ @counter = 0
_ _ @amount = 0
_ end
_ def start(a)
_ _ @amount = a
_ _ @counter += 1
_ _ c = sprintf("_%05d", @counter)
_ _ n = @name.gsub(/\.\w+$/, "#{c}\\1")
_ _ @file.close if @file
_ _ @file = File.open(n, "w")
_ end
_ def sufficient?
_ _ @amount <= 0
_ end
_ def output(s)
_ _ return if sufficient?
_ _ @amount -= 1
_ _ @file.puts(s)
_ _ finish if sufficient?
_ end
_ def finish
_ _ @file.close() if @file
_ _ @file = nil
_ end
end

File.open('yourpath/数千万行のテキストファイル') do |file|
_ cf = CutoutFile.new('outpath/出力ファイル名雛型.txt')
_ while s = file.gets
_ _ cf.start(切り出す行数) if s.start_with?('特定文字列')
_ _ cf.output(s)
_ end
_ cf.finish
end
    • good
    • 0
この回答へのお礼

プログラムありがとうございます。
どうやって使用するのか教えて下さい。
といいますのエラーが発生してしまいました。

testruby.rb:18: void value expression
_ _ return if sufficient?
testruby.rb:36: syntax error, unexpected end, expecting end-of-input

です。
# coding:WINDOWS-31J
がいるのかと思って文頭につけましたが結果は同じ行でエラーがあるという事でした。
変更した部分は
数千万行のテキストファイル・・・result.txt
切り出す行数・・・10000
です。

お礼日時:2019/12/09 20:48

No.3 の補足



・エクセルのセルには一切書き込みません(バッチ処理みたいなものです)
・Const 行は環境に合わせて直してください
・出力ファイル名と同じものは上書きしますが、事前削除はしていませんので過去データのファイル数の方が多い場合はその分が残ります。事前に自動で削除する事も可能ですが必要ですか?
    • good
    • 0
この回答へのお礼

補足ありがとうございます。
基本、一つのフォルダで一地点のデータ解析となるため、自動削除は大丈夫かなと思ってます。
ありがとうございます。

お礼日時:2019/12/09 14:52

「x 速度. y 速度. x-温度. y-温度.という文字列があれば、その文字列を含み下4000行を切り出して」とありますが宜しければご回答ください。



☆ 文字列について
①「x 速度」などは行に含まれる(含まれるか?で判定する)
②「x 速度」などが行の内容である(同じか?で判定する)
③ その他(詳しく説明して下さい)

☆ 特定文字列について
④ 2000行など特定行内には他の特定文字列は無い、または有っても無視する。
⑤ 2000行など特定行内には他の特定文字列が有ったらそれぞれ処理する。
⑥ その他(詳しく説明して下さい)

☆ 特定文字列の位置について
⑦ 2000行など特定行数ごとのブロックになっている
⑧ 特定文字列の位置はランダムで決まりが無い
⑨ その他(詳しく説明して下さい)
    • good
    • 0
この回答へのお礼

★文字列について
「x 速度. y 速度. x-温度. y-温度.」
というブロックで一行となっています。(たまにz速度.という文字が追加されているファイルもありますが、同一のファイル内は同一の文字以外は出てきません)

★特定文字列について
④の記載通り、特定文字列は一切出てきません

★特定文字列の位置について
⑧のように位置はランダム(観測時間によって異なる)ため決まりがないです。

お礼日時:2019/12/09 13:46

もしかしたらですが、エクセルマクロって一度エクセルのシートに取り込んで処理されているのでしょうか?


エクセルのマクロでシートに取り込まず、直接テキストファイルを作成する事も出来ると思うのですが何か問題があるのでしょうか?
    • good
    • 1
この回答へのお礼

外部参照からvbaを使う場合でも、ファイルが長すぎるかつ重すぎてVBAが回らないため、私の知識でお手上げとなってしまっております。

お礼日時:2019/12/09 12:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!