Ryn
Ryn

Reputation: 37

Read Certain Lines from File

Hi just getting into Ruby, and I am trying to learn some basic file reading commands, and I haven't found any solid sources yet.

I am trying to go through certain lines from that file, til the end of the file.

So in the file where it says FILE_SOURCES I want to read all the sources til end of file, and place them in a file.

I found printing the whole file, and replacing words in the file, but I just want to read certain parts in the file.

Upvotes: 2

Views: 3577

Answers (4)

lottscarson
lottscarson

Reputation: 588

File.open("file_to_read.txt", "r") {|f|
  line = f.gets
  until line.include?("FILE_SOURCES")
    line = f.gets
  end
  File.open("file_to_write.txt", "w") {|new_file|
    f.each_line {|line|
      new_file.puts(line) 
    }
   new_file.close
  }
  f.close 
}

Upvotes: 2

Phrogz
Phrogz

Reputation: 303156

I would do it like this (assuming you can read the entire file into memory):

source_lines = IO.readlines('source_file.txt')
start_line   = source_lines.index{ |line| line =~ /SOURCE_LINE/ } + 1
File.open( 'other_file.txt', 'w' ) do |f|
  f << source_lines[ start_line..-1 ].join( "\n" )
end

Relevant methods:

  • IO.readlines to read the lines into an array
  • Array#index to find the index of the first line matching a regular expression
  • File.open to create a new file on disk (and automatically close it when done)
  • Array#[] to get the subset of lines from the index to the end

If you can't read the entire file into memory, then I'd do a simpler variation on @tadman's state-based one:

started = false
File.open( 'other_file.txt', 'w' ) do |output|
  IO.foreach( 'source_file.txt' ) do |line|
    if started then
      output << line
    elsif line =~ /FILE_SOURCES/
      started = true
    end
  end
end

Welcome to Ruby!

Upvotes: 3

tadman
tadman

Reputation: 211560

Usually you follow a pattern like this if you're trying to extract a section from a file that's delimited somehow:

open(filename) do |f|
  state = nil

  while (line = f.gets)
    case (state)
    when nil
      # Look for the line beginning with "FILE_SOURCES"
      if (line.match(/^FILE_SOURCES/))
        state = :sources
      end
    when :sources
      # Stop printing if you hit something starting with "END"
      if (line.match(/^END/))
        state = nil
      else
        print line
      end
    end
  end
end

You can change from one state to another depending on what part of the file you're in.

Upvotes: 7

millimoose
millimoose

Reputation: 39950

IO functions have no idea what "lines" in a file are. There's no straightforward way to skip to a certain line in a file, you'll have to read it all and ignore the lines you don't need.

Upvotes: 0

Related Questions