在 ruby 脚本中删除文件的最后 n 行的最佳方法是什么?
What's the best way to remove the last n lines of a file in a ruby script?
我收到一个 CSV 文件,它总是在末尾包含额外的行,我想在将数据复制到我的 rails 应用程序的 postgresql 数据库之前将其删除。
我不能将 head
与否定参数一起使用,因为我使用的是 MacOS X。
预处理此文件的干净高效的方法是什么?
现在我正在这样做,但我想知道是否有更少的混搭方式:
# Removes last n rows from the file located at PATH
total = `wc -c < #{PATH}`.strip.to_i
chop_index = `tail -n #{n} #{PATH} | wc -c`.strip.to_i
`dd if=/dev/null of=#{PATH} seek=1 bs=#{total - chop_index}`
这是我能想到的在纯 ruby 中执行此操作的最简单方法,它也适用于大文件,因为它一次处理每一行而不是将整个文件读入内存:
INFILE = "input.txt"
OUTFILE = "output.txt"
total_lines = File.foreach(INFILE).inject(0) { |c, _| c+1 }
desired_lines = total_lines - 4
# open output file for writing
File.open(OUTFILE, 'w') do |outfile|
# open input file for reading
File.foreach(INFILE).with_index do |line, index|
# stop after reaching the desired line number
break if index == desired_lines
# copy lines from infile to outfile
outfile << line
end
end
但是,这比您在我创建的 160mb 文件上发布的速度慢两倍。您可以通过使用 wc
来获取总行数,并使用纯 Ruby 来减少大约三分之一:
total_lines = `wc -l < #{INFILE}`.strip.to_i
# rest of the Ruby File code
另一个警告是你的 CSV 不能在任何单元格内容中有它自己的换行符,在这种情况下,你需要一个 CSV 解析器,并且可以使用 CSV.foreach(INFILE) do |row|
,但它是一个相当在我有限的测试中有点慢,但你上面提到你的单元格应该可以按文件行处理。
也就是说,您使用 wc
和 dd
发布的内容要快得多,所以也许您应该继续使用它。
我收到一个 CSV 文件,它总是在末尾包含额外的行,我想在将数据复制到我的 rails 应用程序的 postgresql 数据库之前将其删除。
我不能将 head
与否定参数一起使用,因为我使用的是 MacOS X。
预处理此文件的干净高效的方法是什么?
现在我正在这样做,但我想知道是否有更少的混搭方式:
# Removes last n rows from the file located at PATH
total = `wc -c < #{PATH}`.strip.to_i
chop_index = `tail -n #{n} #{PATH} | wc -c`.strip.to_i
`dd if=/dev/null of=#{PATH} seek=1 bs=#{total - chop_index}`
这是我能想到的在纯 ruby 中执行此操作的最简单方法,它也适用于大文件,因为它一次处理每一行而不是将整个文件读入内存:
INFILE = "input.txt"
OUTFILE = "output.txt"
total_lines = File.foreach(INFILE).inject(0) { |c, _| c+1 }
desired_lines = total_lines - 4
# open output file for writing
File.open(OUTFILE, 'w') do |outfile|
# open input file for reading
File.foreach(INFILE).with_index do |line, index|
# stop after reaching the desired line number
break if index == desired_lines
# copy lines from infile to outfile
outfile << line
end
end
但是,这比您在我创建的 160mb 文件上发布的速度慢两倍。您可以通过使用 wc
来获取总行数,并使用纯 Ruby 来减少大约三分之一:
total_lines = `wc -l < #{INFILE}`.strip.to_i
# rest of the Ruby File code
另一个警告是你的 CSV 不能在任何单元格内容中有它自己的换行符,在这种情况下,你需要一个 CSV 解析器,并且可以使用 CSV.foreach(INFILE) do |row|
,但它是一个相当在我有限的测试中有点慢,但你上面提到你的单元格应该可以按文件行处理。
也就是说,您使用 wc
和 dd
发布的内容要快得多,所以也许您应该继续使用它。