0

私はPythonを初めて使用するので、構文解析の演習を行う必要があります。ファイルを取得し、それを解析する必要があります(ヘッダーのみ)が、プロセス後、ファイルを同じ形式、同じ拡張子、ディスク内の同じ場所に保持する必要がありますが、新しいヘッダー。

このコードを試しました...

for line in open ('/home/name/db/str/dir/numbers/str.phy'):
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        print linepars

..そしてそれは仕事をします、しかし私は新しい解析でファイルを「上書きする」方法を知りません。

4

5 に答える 5

4

最も簡単な方法ですが、最も効率的ではありません (特に長いファイルの場合) は、ファイル全体を書き直すことです。

これを行うには、2 番目のファイル ハンドルを開いて各行を書き換えます。ただし、ヘッダーの場合は、解析済みのヘッダーを記述します。例えば、

fr = open('/home/name/db/str/dir/numbers/str.phy')
fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense

for line in fr:
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        fw.write(linepars)
    else:
        fw.write(line)

fw.close()
fr.close()

編集:これは を使用しないことに注意してくださいreadlines()。そのため、メモリ効率が高くなります。また、すべての出力行を保存するのではなく、一度に 1 行だけ保存し、すぐにファイルに書き込みます。

クールなトリックとしてwith、入力ファイルでステートメントを使用して、ファイルを閉じる必要がないようにすることができます (Python 2.5+):

fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense

with open('/home/name/db/str/dir/numbers/str.phy') as fr:
    for line in fr:
        if line.startswith('ENS'):
            linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
            fw.write(linepars)
        else:
             fw.write(line)

fw.close()

PSようこそ:-)

于 2011-05-19T17:57:06.937 に答える
2

他の人がここで言っているように、ファイルを開いてそのファイル オブジェクトの.write()メソッドを使用したいとします。

最良のアプローチは、書き込み用に追加のファイルを開くことです。

import os

current_cfg = open(...)
parsed_cfg  = open(..., 'w')
for line in current_cfg:
    new_line = parse(line)
    print new_line
    parsed.cfg.write(new_line + '\n')
current_cfg.close()
parsed_cfg.close()

os.rename(....) # Rename old file to backup name
os.rename(....) # Rename new file into place

tempfileさらに、モジュールを見て、そのメソッドのいずれかを使用して、新しいファイルに名前を付けるか、開く/作成することをお勧めします。個人的には、新しいファイルを既存のファイルと同じディレクトリに配置して、os.renameアトミックに動作するようにすることをお勧めします (指定された構成ファイルは、古いファイルまたは新しいファイルのいずれかを指すことが保証されます。部分的に書き込まれた/コピーされたファイル)。

于 2011-05-19T18:03:23.383 に答える
0

次のコードは仕事をします。
つまり、ファイルを自分自身で上書きします。それがOPが求めたものです。これは、変換が文字を削除するだけであるため可能です。そのため、書き込みを行うファイルのポインターfoは、読み取りを行うファイルのポインターfiの常に BEHIND になります。

import re

regx = re.compile('\AENS([A-Z]+)0+([0-9]{6})')

with open('bomo.phy','rb+') as fi, open('bomo.phy','rb+') as fo:
    fo.writelines(regx.sub('\\1\\2',line) for line in fi)

書き込みは、オペレーティングシステムによって一度に1行ずつ実行されるのではなく、バッファーを介して実行されると思います。したがって、変換された行のプールが書き込まれる前に、いくつかの行が読み取られます。そう思います。

于 2011-12-26T14:16:55.487 に答える
-1

(補足: もちろん、大きなファイルで作業している場合は、必要な最適化のレベルが状況に依存する可能性があることに注意する必要があります。Python は本質的に非常に遅延評価されません。データベースのダンプやログなどの大きなファイルを解析していますが、with句をネストしたり、レイジー ジェネレーターや行ごとのアルゴリズムを使用したりするなどの微調整により、O(1) メモリの動作が可能になります。)

targetFile = '/home/name/db/str/dir/numbers/str.phy'

def replaceIfHeader(line):
    if line.startswith('ENS'):
        return re.sub('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
    else:
        return line

with open(targetFile, 'r') as f:
    newText = '\n'.join(replaceIfHeader(line) for line in f)

try:
    # make backup of targetFile
    with open(targetFile, 'w') as f:
        f.write(newText)
except:
    # error encountered, do something to inform user where backup of targetFile is

編集:提案のためのジェフに感謝

于 2011-05-19T18:07:56.293 に答える
-1
newlines = []
for line in open ('/home/name/db/str/dir/numbers/str.phy').readlines():
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        newlines.append( linepars )
open ('/home/name/db/str/dir/numbers/str.phy', 'w').write('\n'.join(newlines))
于 2011-05-19T17:54:31.660 に答える