Modifier chaque ligne d'un fichier dans Ruby
j'essaie de trouver un moyen simple d'éditer chaque ligne dans un fichier, et j'ai du mal à comprendre comment utiliser le File
classe de le faire.
le fichier que je veux éditer a plusieurs centaines de lignes avec des valeurs séparées par des virgules dans chaque ligne. Je suis seulement intéressé à la première valeur de chaque ligne, et je veux supprimer toutes les valeurs après la première. J'ai essayé de faire ce qui suit:
File.open('filename.txt', 'r+') do |file|
file.each_line { |line| line = line.split(",")[0] }
file.write
file.close
end
Qui ne fonctionne pas car <!-La méthode exige que le contenu soit écrit comme argument.
quelqu'un Pourrait-il m'éclairer sur comment je pourrais obtenir l'effet désiré?
5 réponses
l'une des meilleures solutions(et la plus sûre) est de créer un fichier temporaire en utilisant TempFile, et le déplacer vers l'emplacement d'origine(à l'aide de FileUtils) une fois que vous avez terminé:
require 'fileutils'
require 'tempfile'
t_file = Tempfile.new('filename_temp.txt')
File.open("filename.txt", 'r') do |f|
f.each_line{|line| t_file.puts line.split(",")[0].to_s }
end
t_file.close
FileUtils.mv(t_file.path, "filename.txt")
une Autre façon de modifier le fichier en place est d'utiliser le -i
switch
ruby -F"," -i.bak -ane 'puts $F[0]' file
je pense que vous ne comprenez pas ce que cette ligne
file.each_line { |line| line = line.split(",")[0].to_s }
fait vraiment. Il prend une ligne, la divise sur une virgule, prend la première valeur, la tourne vers une chaîne (qu'elle était déjà), assigne le résultat à la variable block-local 'line'. Et alors?
Il passe à la ligne suivante, et rien n'est fait avec la précédente - c'est tout parti. Voir les autres réponses comment y remédier.
le traitement de fichier utilisant le code diffère considérablement de ce que nous faisons lorsque, par exemple, nous éditons le fichier dans un éditeur de texte. Les opérations de fichiers offertes par les systèmes d'exploitation sont assez limitées en la matière (en raison de nombreuses raisons, en partie historiques - pensez bandes magnétiques).
en bref, vous devriez probablement créer un autre fichier et y écrire des données (Mike a fourni le code pour cela), ou charger le fichier entier en mémoire (ce qui peut être une mauvaise idée si votre fichier est énorme) et l'écraser avec données traitées.
juste pour la pratique, voici comment vous pourriez réellement éditer le fichier en place. Comme vous pouvez le voir, pas la plus jolie vue:
File.open('foo', 'r+') do |file|
write_pos = 0
file.each do |line|
word = line.chomp.split(',').first
read_pos = file.pos
file.pos = write_pos
file.puts word
write_pos = file.pos
file.pos = read_pos
end
file.truncate write_pos
end
le problème avec la réponse acceptée est qu'elle modifie les permissions de fichiers et la propriété (faites attention à cela).
une Autre approche est l'utilisation directe de l'édition à l'intérieur de Ruby (et non à partir de la ligne de commande):
#!/usr/bin/ruby
def inplace_edit(file, bak, &block)
old_stdout = $stdout
argf = ARGF.clone
argf.argv.replace [file]
argf.inplace_mode = bak
argf.each_line do |line|
yield line
end
argf.close
$stdout = old_stdout
end
inplace_edit 'test.txt', '.bak' do |line|
line = line.gsub(/search1/,"replace1")
line = line.gsub(/search2/,"replace2")
print line unless line.match(/something/)
end
si vous ne voulez pas créer une sauvegarde, changez '.bak " pour ".