次のようなテキストファイルがあります。
blah blah
foo1 bar1
foo1 bar2
foo1 bar3
foo2 bar4
foo2 bar5
blah blah
'foo bar'
と'foo1 bar3'
の間に'foo2 bar4'
を挿入します。
これは私がやった方法です:
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)
これは私には有効ですが、かなりratherいように見えます。
Python=でファイルに「擬似インプレース」変更を行う最良の方法は、標準ライブラリのfileinput
モジュールを使用することです:
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,
古いバージョンを保持したい場合はバックアップ拡張機能を指定することもできますが、これはコードと同じように機能します。バックアップ拡張機能として.bak
を使用しますが、変更が正常に完了すると削除します。
適切な標準ライブラリモジュールを使用する以外に、このコードはより単純なロジックを使用します:"foo bar"
で始まる行の実行ごとにfoo1
行を挿入するために、必要なのはブール値だけですそして、現在の行がそのように始まるかどうかに基づいて、問題のブールを無条件に設定できます。あなたが望む正確なロジックがこれとわずかに異なる場合(これはあなたのコードから推測したものです)、それに応じてこのコードを微調整することは難しくないはずです。
アレックスマルテッリの例の適応:
import fileinput
for line in fileinput.input('1.txt', inplace=1):
print line,
if line.startswith('foo1 bar3'):
print 'foo bar'
イテレータはファーストクラスのオブジェクトであることを思い出してください。複数のforステートメントで使用できます。
複雑に見えるif文やフラグをたくさん使わずにこれを処理する方法を次に示します。
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()