17

次のように、Rubyを使用してファイルの先頭に1行追加します。

# initial file contents
something
else

# file contents after prepending "hello" on its own line
hello
something
else

次のコードは、ファイル全体の内容を置き換えるだけです。

f = File.new('myfile', 'w')
f.write "test string"
4

8 に答える 8

24

これはかなり一般的なタスクです。

original_file = './original_file'
new_file = original_file + '.new'

テストを設定します。

File.open(original_file, 'w') do |fo|
  %w[something else].each { |w| fo.puts w }
end

これは実際のコードです:

File.open(new_file, 'w') do |fo|
  fo.puts 'hello'
  File.foreach(original_file) do |li|
    fo.puts li
  end
end

古いファイルの名前を安全な名前に変更します。

File.rename(original_file, original_file + '.old')
File.rename(new_file, original_file)

それが機能することを示します:

puts `cat #{original_file}`
puts '---'
puts `cat #{original_file}.old`

どの出力:

hello
something
else
---
something
else

ファイルを完全にメモリにロードしようとしないでください。これは、RAM割り当てよりも大きいファイルを取得し、マシンがクロールするか、さらに悪いことにクラッシュするまで機能します。

代わりに、1行ずつ読んでください。個々の行の読み取りは依然として非常に高速で、スケーラブルです。ドライブには、元のファイルと一時ファイルを保存するのに十分なスペースが必要です。

于 2011-12-24T11:45:47.100 に答える
6

fwiwこれはうまくいくようです:

#!usr/bin/ruby

f = File.open("myfile", "r+")
lines = f.readlines
f.close

lines = ["something\n"] + lines

output = File.new("myfile", "w")
lines.each { |line| output.write line }
output.close
于 2011-12-24T07:18:44.503 に答える
6

私はこのようなものを思いついた、それは私が見た他の解決策よりも少し説明的で謎めいたものではない:

def file_prepend(file, str)
  new_contents = ""
  File.open(file, 'r') do |fd|
    contents = fd.read
    new_contents = str << contents
  end
  # Overwrite file but now with prepended string on it
  File.open(file, 'w') do |fd| 
    fd.write(new_contents)
  end
end

そして、あなたはそれをこのように使うことができます:

file_prepend("target_file.txt", "hello world!\n")
于 2014-03-21T18:23:21.387 に答える
6

一部の人が言っているように、おそらくこれを大きなファイルには使用しないでくださいが、これは簡単なスタートです。

rd = IO.read 'myfile'
IO.write 'myfile', "hello\n" + rd
于 2014-04-24T23:08:46.343 に答える
3

やりたいことを簡単にできるメカニズムはありません。

代わりに、ファイルを開き、ファイルを削除し、書き込み用に古い名前で新しいファイルを開き、コンテンツを書き込んでから、古いファイルのコンテンツから新しいファイルを書き込む必要があります。これはかなり複雑なサウンドですが、コードでは簡単です。

$ cat prepend.rb 
#!/usr/bin/ruby

File.open("passwd", "r") do |orig|
    File.unlink("passwd")
    File.open("passwd", "w") do |new|
        new.write "test string"
        new.write(orig.read())
    end
end

私が使用したメカニズムはエラーのチェックを気にしないことに注意してください-おそらく各File.open()リクエストとリクエストでエラーを処理する必要がありますFile.unlink()-そしてそれはファイルの内容全体がメモリに収まると想定しています。簡単な例:

$ rm passwd
$ cp /etc/passwd .
$ ./prepend.rb 
$ head passwd
test stringroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
$ 

完全にメモリに収まらない可能性のあるファイルを処理する場合は、次のようなループをコーディングする必要があります(テストされていない-疑似コードと見なす方がよい)。

while (data=orig.read(4096)) {
    new.write(data)
}

別の方法として、一時ファイルに書き込むことができます。書き込みプロセスが成功した場合は、ファイル削除して、一時ファイルの名前を変更します。どちらのアプローチがあなたにとって最も理にかなっています。

于 2011-12-24T07:11:11.813 に答える
2

あなたはこれを試すことができます:

File.copy_stream(myfile,tempfile)
f = File.open(myfile,'w')
f.write("Hello\n#{File.open(tempfile,'r').read}")
f.close
File.delete(tempfile)
于 2011-12-24T10:22:17.747 に答える
0

コマンドラインから、次のことができます。

ruby -i -pe '$_= "prepended text\n"+$_ if $. == 1' myfile

またはより効率的に

ruby -i -pe 'BEGIN { gets; print "prepended text\n" + $_ }; ' myfile

残念ながら、-i(インプレース)オプションは実際にはインプレースではありません(またsed、そのことについてはインプレースオプションでもありません)-私のファイルは、操作後に別のiノードを持ちます。

それは私を悲しくさせました。なぜなら、ファイルの2つのコピーに十分なディスク容量がないと、事実上、巨大なファイルをフィルタリング(追加)することができないからです。

ただし、インプレースで実行することはそれほど難しくありません(最初の行だけでなく、一般的にフィルタリングします)。あなたがする必要があるのは:

1)読み取りと書き込みのポインタが別々になっていることを確認します(または読み取りと書き込み用に別々のFileオブジェクトがあります)2)再書き込みする未読部分がバッファリングされていることを確認します3)フィルタリング操作の場合は最後にファイルに切り捨てます短いファイルで終わるはずです

そのためのラッパークラスを https://github.org/pjump/i_rewriterで作成しました。

それで、あなたはすることができます

Rewriter.new("myfile") do |line, index|
  index == 0 ? "prepended text\n" + line : line
end

または実行可能ファイルを使用して:

$  i_rewriter 'index == 0 ? "prepended text\n" + line : line' myfile

注意して使用してください(中断するとファイルが破損する可能性があります)。

于 2015-07-07T12:52:14.310 に答える
0

純粋ですが、機能します。ファイル関連の操作を最小限に抑えます。

`#!/bin/ruby
inv_file = File.open("./1.txt","r+") { |f|
    #Read file string by-string
    until f.eof?
        #Searching for some
        if f.readline[/condition here/]
            #remember position
            offset = f.pos
            #Find it? - stop reading
            break
        end
    end
    #Remember what contains rest of file
    tail = f.readlines
    #Again to offset
    f.pos = offset
    #insert what necessary
    f.puts "INSERTED"
    #reconstruct tail
    f.write tail.join
    }`
于 2016-03-01T14:56:11.953 に答える