10

現在、次の Unix コマンドを再現しています。

cat command.info fort.13 > command.fort.13

Python で次のように指定します。

with open('command.fort.13', 'w') as outFile:
  with open('fort.13', 'r') as fort13, open('command.info', 'r') as com:
    for line in com.read().split('\n'):
      if line.strip() != '':
        print >>outFile, line
    for line in fort13.read().split('\n'):
      if line.strip() != '':
        print >>outFile, line

これは機能しますが、より良い方法が必要です。助言がありますか?

編集 (2016):

この問題は、4 年後に再び注目を集め始めています。ここで、長い Jupyter Notebook にいくつかの考えを書きました。

問題の核心は、私の質問がreadlines. 私が目指していた答えはもっとよく尋ねられたかもしれません、そしてその質問はよりよく答えられたでしょうread().splitlines()

4

6 に答える 6

15

最も簡単な方法は、単に行を忘れて、ファイル全体を読み取り、それを出力に書き込むことです。

with open('command.fort.13', 'wb') as outFile:
    with open('command.info', 'rb') as com, open('fort.13', 'rb') as fort13:
        outFile.write(com.read())
        outFile.write(fort13.read())

コメントで指摘されているように、入力のいずれかが大きい場合(最初にファイル全体をメモリにコピーするため)、これによりメモリ使用量が高くなる可能性があります。これが問題になる可能性がある場合は、以下も同様に機能します(入力ファイルをチャンクでコピーすることにより)。

import shutil
with open('command.fort.13', 'wb') as outFile:
    with open('command.info', 'rb') as com, open('fort.13', 'rb') as fort13:
        shutil.copyfileobj(com, outFile)
        shutil.copyfileobj(fort13, outFile)
于 2012-07-18T01:22:00.883 に答える
8
def cat(outfilename, *infilenames):
    with open(outfilename, 'w') as outfile:
        for infilename in infilenames:
            with open(infilename) as infile:
                for line in infile:
                    if line.strip():
                        outfile.write(line)

cat('command.fort.13', 'fort.13', 'command.info')
于 2012-07-18T01:20:37.203 に答える
6
#!/usr/bin/env python
import fileinput

for line in fileinput.input():
    print line,

使用法:

$ python cat.py command.info fort.13 > command.fort.13

または、任意の大きな線を許可するには:

#!/usr/bin/env python
import sys
from shutil import copyfileobj as copy

for filename in sys.argv[1:] or ["-"]:
    if filename == "-":
        copy(sys.stdin, sys.stdout)
    else:
        with open(filename, 'rb') as file:
            copy(file, sys.stdout)

使い方は同じです。

またはPython3.3では:を使用しos.sendfile()ます

#!/usr/bin/env python3.3
import os
import sys

output_fd = sys.stdout.buffer.fileno()
for filename in sys.argv[1:]:
    with open(filename, 'rb') as file:
        while os.sendfile(output_fd, file.fileno(), None, 1 << 30) != 0:
            pass

上記のsendfile()呼び出しは、Linux>2.6.33用に作成されています。原則として、sendfile()他のアプローチで使用される読み取り/書き込みの組み合わせよりも効率的です。

于 2013-01-19T05:35:57.490 に答える
1

これはいくつかの方法で単純化できます。

with open('command.fort.13', 'w') as outFile:
  with open('fort.13', 'r') as fort13, open('command.info', 'r') as com:
    for line in com:
      if line.strip():
        print >>outFile, line
    for line in fort13:
      if line.strip():
        print >>outFile, line

さらに重要なことに、shutilモジュールにはcopyfileobj関数があります。

with open('command.fort.13', 'w') as outFile:
  with open('fort.13', 'r') as fort13:
    shutil.copyfileobj(com, outFile)
  with open('command.info', 'r') as com:
    shutil.copyfileobj(fort13, outFile)

これは空白行をスキップしませんが、猫もそれをしませんので、あなたが本当にしたいかどうかはわかりません。

于 2012-07-18T01:23:23.487 に答える
1

ファイルを反復すると、行が生成されます。

for line in infile:
  outfile.write(line)
于 2012-07-18T01:16:32.953 に答える
1

リスト内包表記は、次のような場合に優れています。

with open('command.fort.13', 'w') as output:
  for f in ['fort.13', 'command.info']:
    output.write(''.join([line for line in open(f).readlines() if line.strip()]))
于 2012-11-22T00:02:20.447 に答える