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.
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.
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'
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()