Пропуск первой строки при чтении в файле в 1.9.3 - PullRequest
14 голосов
/ 08 марта 2012

Я использую файл ruby ​​для открытия и чтения текстового файла внутри граблей задача. Есть ли настройка, где я могу указать, что я хочу, чтобы первая строка файл пропущен? Вот мой код:

desc "Import users." 
  task :import_users => :environment do 
    File.open("users.txt", "r", '\r').each do |line| 
      id, name, age, email = line.strip.split(',') 
      u = User.new(:id => id, :name => name, :age => age, :email => email) 
      u.save 
    end 
  end

Я пытался line.lineno, а также делал File.open("users.txt", "r", '\r').each do |line, index| и next if index == 0, но не повезло.

Ответы [ 8 ]

22 голосов
/ 08 марта 2012

Измените each на each_with_index do |line, index| и next if index == 0 будет работать.

17 голосов
/ 04 февраля 2013

функция drop(n) удалит n строки с начала:

File.readlines('users.txt').drop(1).each do |line| 
  puts line
end 

Будет считан весь файл в массив и удалены первые n строкиЕсли вы все равно читаете файл целиком, это, вероятно, самое элегантное решение.

9 голосов
/ 08 марта 2012
File.open("users.txt", "r", '\r') do |file|
  lines = file.lines # an enumerator
  lines.next #skips first line
  lines.each do |line|
    puts line # do work
  end
end

Использование счетчика, который «запоминает», где он находится.

4 голосов
/ 27 декабря 2012
File.readlines('users.txt')[1..-1].join()

Хорошо работает тоже.

4 голосов
/ 08 марта 2012

Вы, вероятно, действительно хотите использовать csv:

CSV.foreach("users.txt", :headers, :header_converters => :symbol, :col_sep => ',') do |row|
  User.new(row).save
end 
1 голос
/ 29 октября 2014

Поскольку несколько ответов (больше не?) Работают в Ruby 1.9.3, здесь приведен рабочий пример трех лучших методов

# this line must be dropped
puts "using drop"
File.readlines(__FILE__).drop(1).each do |line| 
  puts line
end 
puts ""

puts "using a range"
File.readlines(__FILE__)[1..-1].each do |line| 
  puts line
end
puts ""

puts "using enumerator"
File.readlines(__FILE__).each do |file, w|
    lines = file.lines # an enumerator
    lines.next #skips first line
    lines.each do |line|
        puts line
    end
end
1 голос
/ 02 мая 2013

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

f = File.open('users.txt', 'r')
first_line = f.gets
body = f.readlines

Скорее всего, то, что вы хотите, обрабатываетсяпо CSV или FasterCSV, как другие указали.Мой любимый способ обработки файлов со строкой заголовка - это:

FasterCSV.table('users.txt')
0 голосов
/ 17 августа 2018

ОП сказал, что lineno не работает для них, но я предполагаю, что он не был применен правильно. Существует множество способов достичь того, о чем просит OP, но использование lineno может помочь вам сократить код без необходимости использования readlines, что иногда требует слишком много памяти.

Из 1.9.3 документов

f = File.new("testfile")
f.each {|line| puts "#{f.lineno}: #{line}" }

производит:

1: This is line one
2: This is line two
3: This is line three
4: And so on...

Обратите внимание, что это метод, который можно вызывать из файлового объекта, но не объекта, переданного блоку.

   2:     require 'pry'; binding.pry
=> 3:   f.each {|line| puts line.lineno }

[1] pry(#<SomeFile>)> line.lineno
NoMethodError: undefined method `lineno' for #<String:0x00007fa7d682b920>

Вы можете найти тот же пример с идентичным кодом в документах для последней стабильной версии Ruby сегодня (2.5.1).

Итак, если исходить из примера, код может выглядеть как

f = File.new("testfile")
o = File.open("output.txt", w)
f.each do |line|
  next if f.lineno == 1
  o << line
end
...