1. ホーム
  2. python

[解決済み] 追記ではなく、置換・上書きをする

2022-03-02 13:01:59

質問

次のようなコードがあります。

import re
#open the xml file for reading:
file = open('path/test.xml','r+')
#convert to string:
data = file.read()
file.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
file.close()

ここで、ファイル内にある古いコンテンツを新しいコンテンツに置き換えたい。しかし、私のコードを実行すると、ファイル "test.xml" が追加されます。つまり、古いコンテンツに続いて新しいコンテンツ "replaced" が追加されます。古いものを削除して、新しいものだけを残すにはどうしたらよいでしょうか?

解決方法は?

必要なのは seek を書き込む前にファイルの先頭に追加し、その後に file.truncate() インプレース置換を行う場合

import re

myfile = "path/test.xml"

with open(myfile, "r+") as f:
    data = f.read()
    f.seek(0)
    f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))
    f.truncate()

もう一つの方法は、ファイルを読み込んでから、再びそれを open(myfile, 'w') :

with open(myfile, "r") as f:
    data = f.read()

with open(myfile, "w") as f:
    f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))

どちらも truncate また open(..., 'w') を変更します。 ノード の番号が表示されます(Ubuntu 12.04 の NFS と ext4 で2回テストしました)。

ちなみに、これはPythonとはあまり関係ない話です。インタプリタが対応する低レベルのAPIを呼び出すのです。メソッド truncate() は、C言語でも同じように機能します。参照 http://man7.org/linux/man-pages/man2/truncate.2.html