ファイルの特定行を削除する方法

このQ&Aのポイント
  • ファイルの中の特定の行を削除する方法について教えてください。
  • あるファイルの特定の行を高速に削除する方法を知りたいです。
  • ファイルの特定行を削除する際、高速な方法があれば教えてください。
回答を見る
  • ベストアンサー

ファイルの中の特定の行だけを削除したい

あるファイルの特定の行だけを削除したいのですが、高速に行う方法はありませんか? とあるファイルがあり、これは数行~数万行にも及ぶ可能性のある大規模なファイルです。 このファイルの、特定の行を検索してその行だけ削除し、空いてしまった行は詰めたいのですが、どのようにすれば高速に行えますか? かなり遅い方法だと、 xxx = "hoge\n" arr = [] f = open("file") f.each{|line| if line != xxx then arr<<line end } f.close open("file", "w").puts arr.join() などが考えられるのですが、遅すぎて使えないはずです。 速度が求められる処理のため、困ってます。 もしご存じの方がいらっしゃいましたら、教えて頂けませんか?

  • Ruby
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.1

メモリに入りきる大きさならお書きの方法が一番良いと思います。ただ、配列にする必要はないで、 xxx = "hoge\n" out = "" IO.foreach("file") do |line| out << line if line != xxx end open("file","w") do |f| f.write out end 最初に削除する行が、ファイルのかなりうしろの方であることがわかっているなら、その位置(tell)を覚えておいて、書くときに"r+"でオープンしてその位置にseekしてから残りを書くとそこまでを書かない分だけ速いですが。closeしてから、縮まったサイズにtruncateする必要もあります。

inuchokin
質問者

お礼

ありがとうございます! 配列にする必要はないのですね。 <<で文字列に追加できるとは思ってませんでした。 テキストファイルで、それほど大規模ではないはずなので、メモリ範囲ないだろうと想定できます。 なので、こちらのプログラムを参考にさせていただきます! ありがとうございました。

その他の回答 (2)

  • ki073
  • ベストアンサー率77% (491/634)
回答No.3

No2です。 プログラムが間違っていますね。 if line != "hoge\n" then print line を fo.print line if line != "hoge\n" に修正 ついでに速度を測ってみたのですが(都合で正規表現での一致を見ています) まず手元に有った48709行(3.2MBytes)のファイルで 質問欄のプログラム 0.07秒 No.2のRuby(修正あり) 0.08秒 No.2のgrep 0.02秒 差がほとんど無かったので、2922540行に増やして 質問欄のプログラム 5.83秒 No.2のRuby(修正あり) 4.26秒 No.2のgrep 1.74秒 CPUはCore i5 1.6GHz、ストレージはSSDでRuby 1.8.7です。 grepは確かに速いですが、 質問欄のプログラムも結構速いと思いますが、

inuchokin
質問者

お礼

測定までしていただいて、ありがとうございました! SSDとはいえ、とても参考になりました。 今回はNo1さんの例を参考にさせていただくことにします。 また機会があれば宜しくお願いします。 ありがとうございました

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

一番速そうなのはRubyではなくgrepを使うことのように思います。 grep -v -E "^hoge$" infile >outfile Rubyほど正規表現は強力ではないので、単純な場合には使えます。 -vで一致したものが除外されます。 Rubyですが、arr<<line が遅くしていると思います。溜め込まずに一行ずつ出力すれば速くなるはずです。 溜め込んだ場合行数が多くなるとちょっとしんどいと思います。 fi = open("infile") fo=open("outfile", "w") f.each{|line| if line != "hoge\n" then print line } fi.close fo.close 後で出力ファイル名を変更します。 動作確認はしていません。

inuchokin
質問者

お礼

すみません。Rubyであるのは理由があるので変更できません。 このプログラムは他のプログラムの一部を構成しているにすぎないのです。 一時的に他のプログラム(例えばgrep)を呼び出すのも可能かもしれませんが、複雑化しそうなので今回はやめておきます。 もしかしたらするかもしれませんが・・・w やはり配列に貯めこむのは重そうですね。 しかしその例だと、ファイルが2つ存在しています。 ファイルは同一なのです。 ファイルをコピーするのはそのファイルが大規模であればあるほど重くなると思うので、やめておきます。 ありがとうございました。

関連するQ&A

  • ファイルの特定行を取り出したい.

    こちらのサイトを参考にさせていただきました. http://www.namaraii.com/rubytips/?%A5%D5%A5%A1%A5%A4%A5%EB%A5%A2%A5%AF%A5%BB%A5%B9 やりたいことはファイルにアクセスして2行目,3行目の文字列をとってくることです. ===foo=== hoge hige foobar File::open("foo") {|content|  puts content.readlines[1]  puts content.readlines[2] } このようなプログラムだと, hige nil となります.ですが,以下のように分割するとうまくいきます. File::open("foo") {|content|  puts content.readlines[1] } File::open("foo") {|content|  puts content.readlines[2] } hige foobar できればopenは一回だけで済ませたいのですが可能でしょうか? Ruby初心者なのでくだらない質問かもしれませんが,ご教授ねがいます.

    • ベストアンサー
    • Ruby
  • テキストファイルの特定行の削除方法

    Accessからテキストファイルのオープンし、特定行を削除してクローズしたいです。どうすれば良いでしょうか。

  • Ruby flagによるファイルの特定行の抽出

    こんばんは。 Rubyでファイルの特定行を抽出するプログラムを作っているのですが、 flagを立てて特定の場所から特定の場所までを指定する方法をとりたいと思っています。 ある程度までは書いたのですが、そこからどうすれば良いのかが分かりません。 なにとぞ御教授、御添削の程お願い致します。 data = File.open(fpath) do |f| 6 7 f.each_line do |line| 8 9 line.gsub!(/前事業年度特定投資株式/,"前事業年度") 10 line.gsub!(/当事業年度特定投資株式/,"当事業年度") 11 12 13 line.gsub!(/保有目的が純投資目的である/,"EOF") 14 line.gsub!(/保有目的が純投資目的の/,"EOF") 15 16 # next unless line =~ /保有目的が純投資目的以外/ .. line =~ /EOF/ 17 18 19 if $flag == 1 20 text << line.chomp unless line =~ /^\s+$/ 21 22 if line =~ /保有/ 23 $flag = 1 24 else if line =~ /EOF/ 25 $flag = 0

    • ベストアンサー
    • Ruby
  • CSVファイルの特定行の削除

    CSVファイルの特定行を削除するということは可能なのでしょうか? 可能であれば教えて頂けないでしょうか? お願いします。

  • getパラメータでメルアド削除

    URLパラメータでたとえば http://www.hoge.hoge.delphp?del_mail=hoge01@hoge.hoge と送信したときにログファイルから削除し再書き込みしたいのですが、うまくいきません。 *ログファイルには重複したファイルもありますので重複ファイルも同時に削除できればいいのですが・・・ 下記コードに対するアドバイス下さい。 mail.log------------- hoge01@hoge.hoge hoge02@hoge.hoge hoge03@hoge.hoge hoge04@hoge.hoge hoge01@hoge.hoge hoge02@hoge.hoge 上記のようなメールアドレスだけのログがあります。 del.php------------------------------------- $array_file = file("./list.db"); $name = htmlspecialchars($_GET['del_mail'], ENT_QUOTES); unset($array_file[$name]); foreach ($array_file as $line) { $file_new .= $line; } file_put_contents("./list.db" , $file_new , LOCK_EX );

    • 締切済み
    • PHP
  • Rubyで特定の位置に1行を挿入したい

    あるファイルを読み込んで、もし行と行の間に、特定の文字列がなければその行間に文字列を挿入したいと思っています。 読み込むファイルは以下のような形になっています。 sample.txt ------------------------------------------ @config['network']['dns'].sort.each do | key, value | case key when xxx ........ @config['network'].sort.each do | key, value | case key when xxx ........ このような形が続く。。。 ------------------------------------------ この場合に、"@config~"の行と、"case key"の行の間にもし何の行もなければ、そこに"next unless value"の行を挿入したいのですが、どのようにすれば可能でしょうか。 期待値 ------------------------------------------ @config['network']['dns'].sort.each do | key, value | next unless value case key when xxx ........ @config['network'].sort.each do | key, value | next unless value case key when xxx ........ ------------------------------------------ 初心者の質問ですみませんが、教えていただけると助かります。 よろしくお願いいたします。

  • gccコンパイラのプログラムでファイルの特定行削除をしたい

    初心者な質問で申し訳ありません。。 Linuxでプログラムの勉強をしています。 その中でファイルにデータを書込み、 あとでそこを検索してその行を削除するというプログラムを作成しており、そのためのCの関数リファレンスやいくつか書籍を調べてみたのですが、 ファイルから特定の行を削除するという具体的な方法を見つけることができませんでした。 今のところ現実的なのは 1.特定の行より前の行までを別のファイルに書き出し。(コピー) 2.特定の行より後ろの行以降を別のファイルに書き出し(コピー) 3.コピー元のファイルを削除する。 4.コピーしたファイルを3.で削除した名前に変える。 なのですが、これ以外の方法をご存知の方、御教授いただけますでしょうか? なお、Qtの勉強もかねてなのでコンパイラはgcc限定としております。

  • PHPでCSVファイルの特定行のみ表示

    PHPでCSVファイルを読み込ませるにあたり、「クエリで指定した特定の1行だけ」を取りだしたいと考えています。 下記だと、1行目からクエリで指定した特定行までの抽出が可能です。 hoge.php?repert=5  → 1から5行目までが表示される。 従い、下記から特定行より上の行を削除すれば、当方が考えている「クエリで指定した特定の1行だけ」を取りだすことになりますが、その方法がわかりません。 ご教示いただきたくお願いいたします。 <?php $repeat = $_GET['repert']; $fp = fopen("file2.csv", "r"); $count = 1; while ($data = fgetcsv($fp, 10000)) { if ($count > $repeat) { break; } print <<<EOD $data[0]・$data[1]・$data[2]<br> EOD; $count++; } fclose ($fp) ?>

    • ベストアンサー
    • PHP
  • 1行だけ削除。

    log.logというログファイルの中のデータから、 NAME=hoge&GROUP=hogehoge というような1行だけを削除する場合はどのようにしたらいいのでしょうか?

    • 締切済み
    • CGI
  • array_searchを使って外部ファイルから目的のキーを取得したい

    array_searchを使って外部ファイルから目的のキーを取得したいのですが どうしてもFALSEを返されてしまいます。 以下が構文です。 <?php $file = file_get_contents("arr.php"); $arr =explode("\n",$file); $delstr="DEF"; $hoge = in_array($delstr,$arr,1); if($hoge !== false){ array_splice($arr,$hoge,1); } var_dump($hoge); print_r($arr); ?> 3日くらい悩んでいます。 どうかご教授よろしくお願い致します。

    • 締切済み
    • PHP

専門家に質問してみよう