Modificar una línea en un archivo?


#1

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


#2

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


#3

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


#4

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


#5

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


#6

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


#7

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.


#8

Ah, claro. Ese 2 del final …

Gracias de nuevo


#9

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.


#10

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


#11

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


#12

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…


#13

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