2012-07-18 28 views
6

Tôi hiện đang tái tạo lệnh Unix sau:tạo lại lệnh cat Unix bằng Python

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

bằng Python như sau:

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 

mà làm việc, nhưng đó có phải là một cách tốt hơn . Bất kỳ đề xuất?

Chỉnh sửa (2016):

Câu hỏi này đã bắt đầu nhận được sự chú ý trở lại sau bốn năm. Tôi đã viết một số suy nghĩ trong một Máy tính xách tay Jupyter dài hơn here.

Điểm mấu chốt của vấn đề là câu hỏi của tôi liên quan đến hành vi (bất ngờ của tôi) của readlines. Câu trả lời tôi nhắm tới có thể đã được yêu cầu tốt hơn, và câu hỏi đó sẽ được trả lời tốt hơn với read().splitlines().

+0

['cat.py' cho Python 3] (https://gist.github.com/zed/cda879d141081e5764bd). – jfs

Trả lời

11

Cách đơn giản nhất có thể đơn giản chỉ để quên đi những dòng này, và chỉ cần đọc trong toàn bộ tập tin, sau đó viết nó vào đầu ra:

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

Như đã chỉ ra trong một chú thích , điều này có thể gây ra mức sử dụng bộ nhớ cao nếu một trong hai đầu vào lớn (vì nó sao chép toàn bộ tệp vào bộ nhớ trước). Nếu điều này có thể là một vấn đề, sau đây sẽ chỉ làm việc cũng như (bằng cách sao chép các tập tin đầu vào trong khối):

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) 
+1

Bạn ít nhất nên sử dụng 'shutil.copyfileobj' ... –

1

Lặp lại quá trình tạo một dòng.

for line in infile: 
    outfile.write(line) 
6
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') 
+0

+1. Có thể đọc/ghi dưới dạng một khối, chứ không phải dòng. – pepr

+1

Có, nếu nó không phải là thực tế là OP dường như muốn để dải trống, tôi sẽ làm điều đó trong khối lớn hơn. – kindall

1

Bạn có thể đơn giản hóa này trong một vài cách sau:

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 

Quan trọng hơn, module shutil có chức năng 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) 

này không bỏ qua dòng trống, nhưng mèo không làm điều đó một trong hai, vì vậy tôi không chắc chắn rằng bạn thực sự muốn.

1

List comprehensions là tuyệt vời cho những thứ như thế này:

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()])) 
5
#!/usr/bin/env python 
import fileinput 

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

Cách sử dụng:

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

Hoặc để cho phép tùy ý dòng lớn:

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

Việc sử dụng là như nhau .

Hoặc trên Python 3.3 sử dụng 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 

Các sendfile() cuộc gọi trên được viết cho Linux> 2.6.33.Về nguyên tắc, sendfile() có thể hiệu quả hơn kết hợp đọc/ghi được sử dụng bởi các cách tiếp cận khác.

Các vấn đề liên quan