Forum: Rails-ES Modificar una línea en un archivo ?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Luis V. (Guest)
on 2007-02-05 12:51
(Received via mailing list)
Buenas, me gustaría saber si esto se puede hacer:

Quiero que mi proceso ruby lea un archivo y cuando encuentre una línea
que cumpla una determinada condición, modifique la línea en el
archivo.

Tengo:

   for linea in archivo
      if linea.index("password ")
        db_config.write("password: root")
      end
   end
Luis V. (Guest)
on 2007-02-05 12:53
(Received via mailing list)
Buenas, me gustaría saber si esto se puede hacer:

Quiero que mi proceso ruby lea un archivo y cuando encuentre una línea
que cumpla una determinada condición, modifique la línea en el
archivo.

Tengo:
 f = File.new("archivo.txt")
   for linea in archivo
      if linea.index("una cosa")
        linea.write("otra cosa")
      end
   end

Pero claro, así no hace nada


Alguna ayuda?

Por cierto, el anterior mensaje lo he mandado sin querer, así que olvidaos
de
él
Gracias
Manuel González Noriega (Guest)
on 2007-02-05 13:08
(Received via mailing list)
> Tengo:
>  f = File.new("archivo.txt")
>    for linea in archivo
>       if linea.index("una cosa")
>         linea.write("otra cosa")
>       end
>    end

Una forma a lo mejor más segura podría ser:

1) Copiar archivo.txt a archivo-orig.txt
2) Crear un archivo-new.txt vacio
3) Leer el archivo-orig.txt línea a línea y por cada una meter en
archivo-new.txt lo que corresponda
4) Copiar archivo-new.txt a archivo.txt

De esta forma conservas el archivo original como copia de seguridad.
Incluso en el paso 4 podrías optar por un ln -s en vez de un cp.





--
Manuel
http://linkja.com * un agregador de tendencias
http://simplelogica.net
http://simplelogica.net/logicola
Sebastian D. (Guest)
on 2007-02-05 16:14
(Received via mailing list)
On Feb 5, 2007, at 5:51 AM, Luis V. wrote:

>         linea.write("otra cosa")
>       end
else
  linea.write(linea)    # o algo asi.
>    end
>
> Pero claro, así no hace nada
>
>

Si nos vamos por los rubismos, seria algo asi:

File.open("archivo2.txt") do |output|
   File.read("archivo.txt").each { | line |   output << (line =~ /una
cosa/) ? "otra cosa" : line }
end
Xavier N. (Guest)
on 2007-02-05 17:29
(Received via mailing list)
On Feb 5, 2007, at 11:50 AM, Luis V. wrote:

>         db_config.write("password: root")
>       end
>    end

En linea de comandos puedes usar -pi:

   fxn@feynman:~/tmp$ cat foo.txt
   foo
   bar
   baz
   fxn@feynman:~/tmp$ ruby -pi -we 'gsub!(/baz/, "woo")' foo.txt
   fxn@feynman:~/tmp$ cat foo.txt
   foo
   bar
   woo

En codigo se puede tambien hacer eso via la variable global $-i:

   # extension para fichero de backup, cadena vacia si ninguno
   $-i = ''

   ARGV.replace(['foo.txt'])
   ARGF.each_line do |line|
     print line.gsub(/woo/, "baz")
   end

En Perl la solucion canonica a esto en codigo es usar el modulo
estandard Tie::File, que permite manipular un archivo de texto como
si se tratara de un array de lineas, pero he buscado un poco y no
parece que este portado a Ruby.

-- fxn
Juanjo B. (Guest)
on 2007-02-05 17:59
(Received via mailing list)
Con ruby, puedes crearte un array con las lineas de un archivo con el
método
readlines

lineas=IO.readlines("archivo.txt")
lineas[0] => "primera linea"

No manipulas el archivo directamente pero puedes modificar las lineas
que
quieras cómodamente y luego hacer un write.

Un saludo,
Juanjo


----- Original Message -----
On Feb 5, 2007, at 11:50 AM, Luis V. wrote:

>         db_config.write("password: root")
>       end
>    end

En linea de comandos puedes usar -pi:

   fxn@feynman:~/tmp$ cat foo.txt
   foo
   bar
   baz
   fxn@feynman:~/tmp$ ruby -pi -we 'gsub!(/baz/, "woo")' foo.txt
   fxn@feynman:~/tmp$ cat foo.txt
   foo
   bar
   woo

En codigo se puede tambien hacer eso via la variable global $-i:

   # extension para fichero de backup, cadena vacia si ninguno
   $-i = ''

   ARGV.replace(['foo.txt'])
   ARGF.each_line do |line|
     print line.gsub(/woo/, "baz")
   end

En Perl la solucion canonica a esto en codigo es usar el modulo
estandard Tie::File, que permite manipular un archivo de texto como
si se tratara de un array de lineas, pero he buscado un poco y no
parece que este portado a Ruby.

-- fxn


_______________________________________________
Ror-es mailing list
removed_email_address@domain.invalid
http://lists.simplelogica.net/mailman/listinfo/ror-es
Luis V. (Guest)
on 2007-02-05 18:20
(Received via mailing list)
Gracias por las respuestas, pero no he conseguido que vaya...

En el ejemplo que me ha dicho sebastián he hecho
así:
File.open("fichero.txt","r+") do  |output|
 File.read("fichero.txt").each { | line |   output << (line =~ /una
cosa/) ? "la otra" : line }
end

Y me recarga el archivo, pero no modifica nada.

para el de Juanjo, he hecho algo
así:
   f = File.new("fichero.txt","r+")
   lineas=f.readlines
    for l in lineas
      puts l
      if (l =~ /una cosa/)
         f.write("la otra")
      end
    end

Y me añade el texto al final del archivo.

Los otros dos ejemplos no me valen por como está planteada la
aplicación.
Sebastian D. (Guest)
on 2007-02-05 18:41
(Received via mailing list)
no puedes hacerlo usando el mismo archivo como entrada y como salida.
Tienes que usar otro archivo para la salida, y despues reemplazar el
original.
Luis V. (Guest)
on 2007-02-05 18:50
(Received via mailing list)
Ah, claro. Ese 2 del final  ......


Gracias de nuevo
Luis V. (Guest)
on 2007-02-05 18:52
(Received via mailing list)
Bueno, haciendo mil pruebas, me ha quedado
así:
File.open("archivo.txt","r+") do  |output|
  File.read("archivo.txt").each { | line |
              if line=~/una cosa/
                  output << "  otra cosa\n"
              else
                 output << line
              end
}
end

Le veis algún inconveniente?

Parece que funciona correctamente
Xavier N. (Guest)
on 2007-02-05 21:50
(Received via mailing list)
On Feb 5, 2007, at 5:51 PM, Luis V. wrote:

>
> Le veis algún inconveniente?

No tiene muy buena pinta asi de pronto.

Cuando se abre un archivo el objeto (descriptor de archivo C por
debajo) tiene asociado un modo, un offset de lectura/escritura, hay
buffers por enmedio, etc. propios. Al abrir el archivo por dos veces
esos atributos, que son por descriptor, pueden pisarse unos a otros.

Por ejemplo mira esta sesion:

   fxn@feynman:~/tmp$ cat archivo.txt && echo
   1
   a
   fxn@feynman:~/tmp$ cat foo.rb
   File.open("archivo.txt","r+") do  |output|
     File.read("archivo.txt").each do |line|
       if line =~ /1/
         output << 2
       else
         output << line
       end
     end
   end
   fxn@feynman:~/tmp$ ruby foo.rb
   fxn@feynman:~/tmp$ cat archivo.txt && echo
   2aa

Ves que hay una "a" repetida?

Al trabajar con ficheros las reglas son simples, uno tiene un puntero
siempre donde las opraciones de escritura y lectura se realizan. Por
debajo este puntero se gestiona automaticamente con lecturas y
escrituras, y uno puede manualmente moverlo con seek. Si vas con seek
a un cierto byte de por la mitad ya es responsabilidad tuya el pisar
o no los datos que habia ahi. No hay una manera builtin en C de
borrar o insertar bytes en un offset arbitrario.

-- fxn
Luis V. (Guest)
on 2007-02-06 11:17
(Received via mailing list)
Bueno. Finalmente he utilizado un archivo temporal como me habéis
recomendado, pero ahora no sé como sobreescribir con el archivo generado
el
original, y no encuentro ningún método que haga algo parecido en rdoc.

¿Alguna ayuda?

Gracias
Luis V. (Guest)
on 2007-02-06 11:24
(Received via mailing list)
Me respondo a mi mismo:

File.delete("archivo_origen")
File.rename("archivo_temporal.txt","archivo_origen")

Supongo que no tendrá más misterio que esto...
This topic is locked and can not be replied to.