重现在Python Unix的cat命令(Reproduce the Unix cat comman

2019-06-26 08:44发布

我目前再现以下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):

这个问题已经开始在四年后再次受到关注。 我写了更长Jupyter笔记本电脑的一些想法在这里 。

问题的关键是,我的问题是(由我意外)有关的行为readlines 。 我的目标是朝着答案可能已经更好地问,这个问题会与被更好的回答read().splitlines()

Answer 1:

最简单的方法可能是简单地算了一下线,只是在整个文件中读取,然后将它写入到输出:

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)


Answer 2:

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')


Answer 3:

#!/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)

用法是相同的。

或Python的3.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()可以比读取的组合更有效/写使用其他方法。



Answer 4:

遍历文件产生线。

for line in infile:
  outfile.write(line)


Answer 5:

您可以在几个方面简化了这一点:

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)

这不跳过空白行,但猫不会做,要么,所以我不知道你真的想。



Answer 6:

List内涵是真棒这样的事情:

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()]))


文章来源: Reproduce the Unix cat command in Python
标签: python cat