Dateien mit der Reißverschlussmethode / späten Zusammenführung zusammenführen

7

Ich suche nach einer guten Methode, um zwei oder mehr Dateien Zeile für Zeile mit der Zipper-Methode (auch als späte Zusammenführung bezeichnet) zusammenzuführen. Angenommen, wir haben drei Dateien, sollte das Ergebnis folgendermaßen aussehen:

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

BEARBEITEN

Ich habe ein kleines Python-Skript geschrieben, das dazu in der Lage ist:

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

Ich frage mich immer noch, ob es ein Standardwerkzeug oder eine clevere Kombination von ihnen gibt, die dasselbe tun.

scai
quelle

Antworten:

6

Ich benutze normalerweise pastevon coreutilsfür diese Art von Dingen:

paste -d'\n' file1 file2 file3
Thor
quelle
Schön, ein Standardwerkzeug. Druckt aber leider pasteviele Leerzeilen, wenn die Dateien ungleich lang sind.
Scai
Je nachdem, was Sie benötigen, können Sie die Leerzeilen entfernen, indem Sie Folgendes anhängen : | grep -v '^$'.
Thor
Das ist richtig, funktioniert aber natürlich nur, wenn die angegebenen Dateien selbst keine Leerzeilen enthalten.
Scai
2

Ich habe ein kleines Perl-Skript geschrieben, das dies tut

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

Speichern Sie es in einer Datei und rufen Sie es auf

script.pl file1 file2 file3 ... > merge

Das ist mindestens eine Möglichkeit, Ihre Aufgabe zu lösen.

user1146332
quelle
Vielen Dank für Ihr nettes Skript, aber leider kann ich nur eine Antwort akzeptieren, daher habe ich die mit einem Standardwerkzeug ausgewählt.
Scai
2

Eine andere Python-Version, die nicht alle Dateien gleichzeitig in den Speicher lesen muss:

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:~$ 

Ersetzen Sie izip_longest durch zip_longest und es funktioniert auch in Python 3.x.

Paddy3118
quelle
Vielen Dank für Ihr nettes Skript, aber leider kann ich nur eine Antwort akzeptieren, daher habe ich die mit einem Standardwerkzeug ausgewählt.
Scai