Cómo leer líneas de un archivo en Ruby


Estaba tratando de usar el siguiente código para leer líneas de un archivo. Pero al leer un archivo , el contenido está todo en una línea:

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line}"
end

Pero este archivo imprime cada línea por separado.


Tengo que usar stdin, como ruby my_prog.rb < file.txt, donde no puedo asumir cuál es el carácter final de línea que usa el archivo. ¿Cómo puedo manejarlo?

Author: the Tin Man, 2011-05-16

8 answers

Creo que mi respuesta cubre sus nuevas preocupaciones sobre el manejo de cualquier tipo de fin de línea, ya que tanto "\r\n" como "\r" se convierten al estándar de Linux "\n" antes de analizar las líneas.

Para soportar el carácter "\r" EOL junto con el "\n" regular, y "\r\n" desde Windows, esto es lo que haría:

line_num=0
text=File.open('xxx.txt').read
text.gsub!(/\r\n?/, "\n")
text.each_line do |line|
  print "#{line_num += 1} #{line}"
end

Por supuesto, esto podría ser una mala idea en archivos muy grandes, ya que significa cargar todo el archivo en la memoria.

 126
Author: Olivier L.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-17 17:52:05

Ruby tiene un método para esto:

File.readlines('foo').each do |line|

Http://ruby-doc.org/core-1.9.3/IO.html#method-c-readlines

 457
Author: Jonathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-17 17:52:32
File.foreach(filename).with_index do |line, line_num|
   puts "#{line_num}: #{line}"
end

Esto ejecutará el bloque dado para cada línea en el archivo sin sorber todo el archivo en la memoria. Véase: IO:: foreach .

 304
Author: talabes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-17 23:14:41

Su primer archivo tiene finales de línea Mac Classic (eso es "\r" en lugar de la habitual "\n"). Ábrelo con

File.open('foo').each(sep="\r") do |line|

Para especificar las terminaciones de línea.

 16
Author: Josh Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-16 03:36:18

Es debido a las líneas finales en cada línea. Utilice el método chomp en ruby para eliminar la línea final ' \n 'o' r ' al final.

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line.chomp}"
end
 5
Author: Sreenivasan AC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-30 05:45:20

Soy parcial al siguiente enfoque para los archivos que tienen encabezados:

File.open(file, "r") do |fh|
    header = fh.readline
    # Process the header
    while(line = fh.gets) != nil
        #do stuff
    end
end

Esto le permite procesar una línea (o líneas) de encabezado de manera diferente a las líneas de contenido.

 5
Author: Ron Gejman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-30 16:55:31

¿Qué tal si recibe?

myFile=File.open("paths_to_file","r")
while(line=myFile.gets)
 //do stuff with line
end
 5
Author: JBoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-19 19:47:18

No olvide que si le preocupa leer en un archivo que podría tener líneas enormes que podrían inundar su RAM durante el tiempo de ejecución, siempre puede leer el archivo piece-meal. Vea " Por qué es malo sorber un archivo".

File.open('file_path', 'rb') do |io|
  while chunk = io.read(16 * 1024) do
    something_with_the chunk
    # like stream it across a network
    # or write it to another file:
    # other_io.write chunk
  end
end
 4
Author: Nels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:27