在Ruby中编辑文件中的每一行

我正在尝试找到一种编辑文件中每一行的简单方法,而我在理解如何使用File类时遇到一些麻烦。

我想编辑的文件有几百行,每行有逗号分隔值。 我只对每行中的第一个值感兴趣,并且我希望在第一个值之后删除所有值。 我试着做以下事情:

 File.open('filename.txt', 'r+') do |file| file.each_line { |line| line = line.split(",")[0] } file.write file.close end 

哪个不起作用,因为File.write方法要求将内容写为参数。

有人可以告诉我如何达到预期的效果吗?

一个更好的解决方案(也是最安全的)是使用TempFile创建一个临时文件,并在完成后将其移动到原始位置(使用FileUtils ):

  require 'fileutils' require 'tempfile' t_file = Tempfile.new('filename_temp.txt') File.open("filename.txt", 'r') do |f| f.each_line{|line| t_file.puts line.split(",")[0].to_s } end t_file.close FileUtils.mv(t_file.path, "filename.txt") 

另一种修改文件的方法是使用-i开关

 ruby -F"," -i.bak -ane 'puts $F[0]' file 

我想你误解了这一行

 file.each_line { |line| line = line.split(",")[0].to_s } 

真的。 它需要一行,在逗号上拆分,取第一个值,将其转换为字符串(它已经是),将结果赋给块本地变量’line’。 然后?
它继续下一行,并没有完成前一个 – 它已经全部消失了。 请参阅其他答案如何解决这个问题。

使用代码进行文件处理与我们在文本编辑器中编辑文件时的操作大不相同。 操作系统提供的文件操作在这方面非常有限(由于许多,部分历史原因 – 认为磁带)。

简而言之,您应该创建另一个文件并向其写入数据(Mike提供了相应的代码),或者将整个文件加载到内存中(如果文件很大,这可能是个坏主意)并用处理过的数据覆盖它。

只是为了练习,这里是你如何实际编辑文件的原因。 如你所见,不是最漂亮的景象:

 File.open('foo', 'r+') do |file| write_pos = 0 file.each do |line| word = line.chomp.split(',').first read_pos = file.pos file.pos = write_pos file.puts word write_pos = file.pos file.pos = read_pos end file.truncate write_pos end 

接受的答案的问题是它修改了文件权限和所有权(注意这一点)。

另一种方法是在Ruby内部使用inplace编辑(而不是从命令行):

 #!/usr/bin/ruby def inplace_edit(file, bak, &block) old_stdout = $stdout argf = ARGF.clone argf.argv.replace [file] argf.inplace_mode = bak argf.each_line do |line| yield line end argf.close $stdout = old_stdout end inplace_edit 'test.txt', '.bak' do |line| line = line.gsub(/search1/,"replace1") line = line.gsub(/search2/,"replace2") print line unless line.match(/something/) end 

如果您不想创建备份,请将“.bak”更改为“”。