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

发布于 2024-10-27 06:15:46 字数 381 浏览 5 评论 0原文

我试图找到一种编辑文件中每一行的简单方法,但在理解如何使用 File 类来执行此操作时遇到了一些困难。

我要编辑的文件有数百行,每行都有逗号分隔的值。我只对每行中的第一个值感兴趣,并且我想删除第一个值之后的所有值。我尝试执行以下操作:

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

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

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

I'm trying to find a simple way of editing each line in a file, and I'm having some trouble understanding how to use the File class to do so.

The file I want to edit has several hundred lines with comma separated values in each line. I'm only interested in the first value in each line, and I want to delete all values after the first one. I tried to do the following:

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

Which doesn't work because File.write method requires the contents to be written as an argument.

Could someone enlighten me as to how I could achieve the desired effect?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甜嗑 2024-11-03 06:15:46

更好的解决方案(也是最安全的)之一是使用 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")

The one of the better solutions(and safest) is to create a temporary file using TempFile, and move it to the original location(using FileUtils) once you are done:

   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")
雨落□心尘 2024-11-03 06:15:46

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

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

Another way to modify the file inplace is to use the -i switch

ruby -F"," -i.bak -ane 'puts $F[0]' file
七婞 2024-11-03 06:15:46

使用代码处理文件与我们在文本编辑器中编辑文件时所做的事情有很大不同。操作系统提供的文件操作在这方面非常有限(由于许多部分历史原因 - 想想磁带)。

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

仅供练习,以下是您实际就地编辑文件的方法。正如你所看到的,这不是最美丽的景象:

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

File processing using code differs substantially from what we are doing when we, for example, edit the file in a text editor. File operations offered by operating systems are quite limited in that matter (due to numerous, partly historical reasons - think magnetic tapes).

In short, you should probably create another file and write data to it (Mike provided code for that), or load entire file in memory (which can be bad idea if your file is huge) and overwrite it with processed data.

Just for practice, here's how you could actually edit file in-place. As you can see, not the prettiest sight:

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
故事和酒 2024-11-03 06:15:46

我认为你误解了这条线的

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

真正作用。它需要一行,用逗号将其分割,获取第一个值,将其转换为字符串(它已经是),将结果分配给块局部变量“line”。然后呢?
它继续到下一行,并且前一行没有做任何事情 - 一切都消失了。请参阅其他答案如何解决此问题。

I think you misunderstand what this line

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

really does. It takes a line, splits it on a comma, takes the first value, turns it to a string (which it was already), assigns the result to the block-local variable 'line'. And then?
It goes on to the next line, and nothing is done with the previous one - it's all gone. See the other answers how to remedy this.

野心澎湃 2024-11-03 06:15:46

已接受答案的问题在于它修改了文件权限和所有权(请注意)。

另一种方法是在 Ruby 中使用就地编辑(而不是从命令行):

#!/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”更改为“”。

The problem with the accepted answer is that it modifies file permissions and ownership (pay attention to that).

Another approach is to use inplace editing inside Ruby (not from the command line):

#!/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

If you don't want to create a backup then change '.bak' to ''.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文