Hợp nhất các tệp bằng phương pháp dây kéo / hợp nhất muộn


7

Tôi đang tìm kiếm một phương pháp tốt đẹp để hợp nhất hai hoặc nhiều tệp theo từng dòng bằng phương pháp dây kéo (còn được gọi là hợp nhất muộn). Giả sử chúng ta có ba tệp, kết quả sẽ như thế này:

line1 file1
line1 file2
line1 file3
line2 file1
line2 file2
line2 file3
...

BIÊN TẬP

Tôi đã viết một kịch bản python nhỏ có khả năng làm điều này:

#!/usr/bin/python

import sys, itertools

fileList = []
for file in sys.argv[1:]:
    f = open(file, "r")
    fileList.append(f.read().split("\n"))

for z in itertools.izip_longest(*fileList):
    print "\n".join([i for i in z if i is not None])

Tôi vẫn tự hỏi nếu có bất kỳ công cụ tiêu chuẩn hoặc một sự kết hợp thông minh của họ làm điều tương tự.

Câu trả lời:


6

Tôi thường sử dụng pastetừ coreutilscho loại điều này:

paste -d'\n' file1 file2 file3

Đẹp, một công cụ tiêu chuẩn. Nhưng không may pastein rất nhiều dòng trống nếu các tệp có độ dài không bằng nhau.
SCAI

Tùy thuộc vào những gì bạn cần, bạn có thể xóa các dòng trống bằng cách nối thêm : | grep -v '^$'.
Thor

Điều đó đúng, nhưng tất nhiên chỉ hoạt động nếu các tệp được chỉ định không có các dòng trống.
14:30

2

tôi đã viết một kịch bản perl nhỏ, làm điều này

#!/usr/bin/perl

do { open($fh[$_], "<$ARGV[$_]") or die("'$ARGV[$_]' does not exist") } for(0..$#ARGV);


for($i=0;;$i++) {
    $j=$#ARGV+1;

    $fh = $fh[$i%$j];
    if ( $_ = <$fh> ) {
        print $_;
    } else {
        $end |= 2**($i%$j);
    }

    if($end == (2**($j))-1) {
        last;
    }
}

close($_) for(@fh);

lưu nó vào một tập tin gọi nó như

script.pl file1 file2 file3 ... > merge

Đó là ít nhất một khả năng để giải quyết nhiệm vụ của bạn.


Cảm ơn kịch bản hay của bạn, nhưng tiếc là tôi chỉ có thể chấp nhận một câu trả lời nên tôi đã chọn câu trả lời bằng công cụ tiêu chuẩn.
scai

2

Một phiên bản Python khác không cần phải đọc tất cả các tệp vào bộ nhớ cùng một lúc:

paddy$ more f[123].tmp
::::::::::::::
f1.tmp
::::::::::::::
line1 file1
line2 file1
line3 file1
::::::::::::::
f2.tmp
::::::::::::::
line1 file2
line2 file2
line3 file2
line4 file2
::::::::::::::
f3.tmp
::::::::::::::
line1 file3
line2 file3
line3 file3
line4 file3
line5 file3
paddy$ python2.7 -c 'import sys, itertools
files = [open(fname) for fname in sys.argv[1:]]
sys.stdout.write("".join("".join(lines) for lines in itertools.izip_longest(*files, fillvalue="") ))' f[123].tmp
line1 file1
line1 file2
line1 file3
line2 file1
line2 file2
line2 file3
line3 file1
line3 file2
line3 file3
line4 file2
line4 file3
line5 file3
paddy@paddy-ThinkPad-T61:~$ 

Thay thế izip_longest bằng zip_longest và nó cũng hoạt động trong Python 3.x.


Cảm ơn kịch bản hay của bạn, nhưng tiếc là tôi chỉ có thể chấp nhận một câu trả lời nên tôi đã chọn câu trả lời bằng công cụ tiêu chuẩn.
scai
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.