9654


テキストファイルがあり，それの編集，例えば文字列置換をしたいとします．具体的に

  * 6 を 9 にすべて置換したい

`sed` でも `vim -c '%s/6/9/g' -c ':wq' origfile` でもできるでしょうが，実際の処理はもう少し複雑で，
~~`sed` は turing complete とはいえ ~~ たとえば Python で処理全体を書きたいです．[回答は Python
以外の言語についてでも大丈夫です]

この場合に，（元の文字列）→（処理後の文字列）の変換は問題なく書けますが，その結果をファイルに反映する処理をどうするのがよいのか迷っています．「一行ごと（でも何でも）元のファイルを読み込み，処理後の文字列を全部一時ファイルに書き込み，`mv
tempfile
original`」というのが唯一思いつく（そしてきちんと動く）方法なのですが，必ずファイルを全コピー相当になってしまうのが無駄が多いような気もしてしまいます．ごくごく直観的，そしてナイーブには変更のあったところだけ書き込みたい(原理的に無理な気がしてきていますが)．底まで行かずともなにかうまい方法はありませんか，それともこれで正しいやり方なのでしょうか．


CC BY-SA 3.0
2015-04-28T02:53:13.153
9633
2015-06-06T17:49:07.750
2901
question
python テキストファイル
例えば Python からテキストファイルの編集を行いたいが，保存時1行ずつ一時ファイルに書き込む以外にうまい方法はあるか


# 既存の回答

本家SOの既存の回答にはいくつか近いものがありました。

[Editing specific line in text file in
python](https://stackoverflow.com/questions/4719438/editing-specific-line-in-
text-file-in-python)

質問でも触れられている、一時ファイルを介するテクニックもすでにありました。

[Search and replace a line in a file in
Python](https://stackoverflow.com/questions/39086/search-and-replace-a-line-
in-a-file-in-python)

個人的には、open()関数で`w`モードを指定するとファイルが空にされるという特徴をうまく使っている、前者のページのBest
Answerがよいと思います。これを今回の例に対応させるならば、

[code]

    data[1] = 'Mage\n'
    
[/code]

の部分を

[code]

    for i in range(len(data)):
        data[i] = data[i].replace('6', '9')
    
[/code]

のように変えれば期待した動作をするはずです。

* * *

データは基本的にメディアに詰め詰めで記録されている以上、コメントでyohjpさんがおっしゃっているように文字列長が不変であるという制約条件を付けた上で直にバイナリをいじるなどしないと特定箇所だけの書き換えはできません。よって完璧な回答はできませんが、ご参考までに。


CC BY-SA 3.0
2015-04-28T14:39:00.967
9654
2015-04-28T14:50:46.330
2017-05-23T12:38:55.307
-1
197
9633
answer


別口でインデックスファイルをつくってよければ、元のファイルを一旦読み込んで索引をつくり、編集内容はアペンドするだけにして、インデックスを更新するということやればいいわけです。こうすると高速に読み書き可能です。編集差分やインデックスが大きくなってきたらガベージコレクトします。

同じテクニックはPostgresqlのようなデータベース, MS-Office(95の時代から), CD-
ROMのファイルを仮想的に読み書きする仕組み、などなどで使われています。


CC BY-SA 3.0
2015-06-06T17:49:07.750
11052
2015-06-06T17:49:07.750
7837
9633
answer