Как получить определенную строку из файла

Можно ли извлечь определенную строку из файла, зная его номер строки? Например, просто введите содержимое строки N в виде строки из файла "text.txt"?

Ответы

Ответ 1

Попробуйте одно из этих двух решений:

file = File.open "file.txt"

#1 solution would eat a lot of RAM
p [*file][n-1]

#2 solution would not
n.times{ file.gets }
p $_

file.close

Ответ 2

Вы можете получить его по индексу от readlines.

line = IO.readlines("file.txt")[42]

Используйте это только в случае небольшого файла.

Ответ 3

def get_line_from_file(path, line)
  result = nil

  File.open(path, "r") do |f|
    while line > 0
      line -= 1
      result = f.gets
    end
  end

  return result
end

get_line_from_file("/tmp/foo.txt", 20)

Это хорошее решение, потому что:

  • Вы не используете File.read, поэтому вы не читаете весь файл в памяти. Это может стать проблемой, если файл имеет размер 20 Мбайт, и вы достаточно часто читаете, чтобы GC не ускорялся.
  • Вы читаете только файл до нужной строки. Если ваш файл имеет 1000 строк, строка 20 будет читать только 20 первых строк в Ruby.

Вы можете заменить gets на readline, если вы хотите поднять ошибку (EOFError) вместо того, чтобы возвращать nil при передаче строки вне границ.

Ответ 4

linenumber=5
open("file").each_with_index{|line,ind|
  if  ind+1==linenumber
    save=line
    # break or exit if needed.
  end
}

или

linenumber=5
f=open("file")
while line=f.gets
  if $. == linenumber # $. is line number
    print "#{f.lineno} #{line}" # another way
    # break  # break or exit if needed
  end
end
f.close

Если вы просто хотите получить строку и ничего не делать, вы можете использовать этот один лайнер

ruby -ne '(print $_ and exit) if $.==5' file

Ответ 5

Файл имеет хороший lineno метод.

def get_line(filename, lineno)
  File.open(filename,'r') do |f|
     f.gets until f.lineno == lineno - 1
     f.gets
  end
end

Ответ 6

Если вы хотите один лайнер и не заботитесь об использовании памяти, используйте (если строки пронумерованы от 1)

lineN = IO.readlines('text.txt')[n-1]

или

lineN = f.readlines[n-1]

если у вас уже открыт файл.

В противном случае было бы лучше сделать вот так:

lineN = File.open('text.txt') do |f|
          (n-1).times { f.gets } # skip lines preceeding line N
          f.gets                 # read line N contents
        end