web-dev-qa-db-fra.com

Insertion d'une ligne à la position spécifiée d'un fichier texte

J'ai un fichier texte qui ressemble à ceci:

blah blah
foo1 bar1
foo1 bar2
foo1 bar3
foo2 bar4
foo2 bar5
blah blah

Maintenant, je veux insérer 'foo bar' entre 'foo1 bar3' et 'foo2 bar4'.

Voici comment je l'ai fait:

import shutil

txt = '1.txt'
tmptxt = '1.txt.tmp'

with open(tmptxt, 'w') as outfile:
    with open(txt, 'r') as infile:
        flag = 0
        for line in infile:
            if not line.startswith('foo1') and flag == 0:
                outfile.write(line)
                continue
            if line.startswith('foo1') and flag == 0:
                flag = 1
                outfile.write(line)
                continue
            if line.startswith('foo1') and flag == 1:
                outfile.write(line)
                continue
            if not line.startswith('foo1') and flag == 1:
                outfile.write('foo bar\n')
                outfile.write(line)
                flag = 2
                continue
            if not line.startswith('foo1') and flag == 2:
                outfile.write(line)
                continue

shutil.move(tmptxt, txt)

Cela fonctionne pour moi, mais semble plutôt moche.

31
Wang Dingwei

La meilleure façon d'apporter des modifications "pseudo-inplace" à un fichier dans Python est avec le module fileinput de la bibliothèque standard:

import fileinput

processing_foo1s = False

for line in fileinput.input('1.txt', inplace=1):
  if line.startswith('foo1'):
    processing_foo1s = True
  else:
    if processing_foo1s:
      print 'foo bar'
    processing_foo1s = False
  print line,

Vous pouvez également spécifier une extension de sauvegarde si vous souhaitez conserver l'ancienne version, mais cela fonctionne dans le même esprit que votre code - utilise .bak comme extension de sauvegarde, mais la supprime également une fois la modification effectuée avec succès.

En plus d'utiliser le bon module de bibliothèque standard, ce code utilise une logique plus simple: pour insérer un "foo bar" ligne après chaque série de lignes commençant par foo1, un booléen est tout ce dont vous avez besoin (suis-je dans une telle course ou non?) et le booléen en question peut être défini inconditionnellement juste selon que la ligne actuelle commence de cette façon ou non. Si la logique précise que vous désirez est légèrement différente de celle-ci (ce que j'ai déduit de votre code), il ne devrait pas être difficile de modifier ce code en conséquence.

57
Alex Martelli

Adapter l'exemple d'Alex Martelli:

import fileinput
for line in fileinput.input('1.txt', inplace=1):
 print line,
 if line.startswith('foo1 bar3'):
     print 'foo bar'
12
Eric Lee

Rappelons qu'un itérateur est un objet de première classe. Il peut être utilisé dans plusieurs instructions for.

Voici un moyen de gérer cela sans beaucoup d'instructions if et d'indicateurs complexes.

with open(tmptxt, 'w') as outfile:
    with open(txt, 'r') as infile:
        rowIter= iter(infile)
        for row in rowIter:
            if row.startswith('foo2'): # Start of next section
                 break
            print row.rstrip(), repr(row)
        print "foo bar"
        print row
        for row in rowIter:
            print row.rstrip()
9
S.Lott