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é?

16
demandé sur phor2 2011-03-28 02:00:44

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")
23
répondu Mike Lewis 2013-08-07 09:43:51

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
10
répondu kurumi 2011-03-28 00:15:18

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.

4
répondu steenslag 2011-03-27 23:40:31

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
4
répondu Mladen Jablanović 2013-04-13 00:22:40

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 ".

2
répondu DavidG 2015-08-18 12:51:28