2012-05-23 6 views
9

Ich verwende den Standard-Join-Befehl, um zwei sortierte Dateien basierend auf Spalte1 zu verbinden. Der Befehl ist ein einfacher Join file1 file2> output_file.Join mehrere Dateien

Aber wie verbinde ich 3 oder mehr Dateien mit der gleichen Technik? beitreten file1 file2 file3> output_file Oben Befehl gab mir eine leere Datei. Ich denke sed kann mir helfen, aber ich bin mir nicht sicher, wie?

Antwort

19

man join:

NAME 
     join - join lines of two files on a common field 

SYNOPSIS 
     join [OPTION]... FILE1 FILE2 

es nur mit zwei Dateien arbeitet.

Wenn Sie drei beitreten müssen, können Sie sich vielleicht zuerst den ersten beiden anschließen und dann dem dritten beitreten.

Versuch:

join file1 file2 | join - file3 > output 

, die die drei Dateien, ohne ein Zwischen temporäre Datei beitreten sollte. - teilt dem Join-Befehl des ersten Eingangsstrom von stdin

+0

was meinst du mit einem Bindestrich für den zweiten Join? Ist es ein besonderes Symbol für Join? –

+0

sehe mein Update. '-' wird von vielen Unix-Programmen als Kurzschrift für stdin/stdout – mata

+0

verstanden. Vielen Dank. –

0

Join verbindet Linien von zwei Dateien auf einem gemeinsamen Feld. Wenn Sie mehr beitreten möchten - tun Sie es in Paaren. Verbinden Sie die ersten beiden Dateien zuerst und fügen Sie dann das Ergebnis mit einer dritten Datei usw. hinzu.

2

Die man-Seite von join besagt, dass sie nur für zwei Dateien funktioniert. So müssen Sie erstellen und Zwischendatei, die Sie später löschen, d.h .:

> join file1 file2 > temp 
> join temp file3 > output 
> rm output 
+4

Oder 'beitreten Kevin

+0

@ Kevin Süß (Datei1 Datei2 beitreten)! Wusste das nicht! – Gnosophilon

9

Man kann mehrere Dateien (N> = 2) verbinden, indem er eine Pipeline von join s rekursiv zu lesen:

#!/bin/sh 

# multijoin - join multiple files 

join_rec() { 
    if [ $# -eq 1 ]; then 
     join - "$1" 
    else 
     f=$1; shift 
     join - "$f" | join_rec "[email protected]" 
    fi 
} 

if [ $# -le 2 ]; then 
    join "[email protected]" 
else 
    f1=$1; f2=$2; shift 2 
    join "$f1" "$f2" | join_rec "[email protected]" 
fi 
+0

Definitiv meine Lieblingsantwort!Allerdings habe ich den Körper der 'join_rec'-Funktion folgendermaßen ersetzt:' f1 = $ 1; f2 = 2 $; Schicht 2; if [$ # -gt 0]; dann; beitreten "$ f1" "$ f2" | join_rec - "$ @"; sonst; beitreten "$ f1" "$ f2"; fi ', ​​um die Notwendigkeit des zweiten 'if' zu eliminieren. Der Aufruf würde wie folgt aussehen: 'join_rec $ @" ' – user43791

+0

@ack Ist es möglich, den Dateinamen als Überschrift in der Ausgabe hinzuzufügen? – user1883491

7

Ich weiß, das ist eine alte Frage, aber für zukünftige Referenz. Wenn Sie wissen, dass die Dateien, die Sie verbinden möchten, ein Muster wie in der Frage haben, z. file1 file2 file3 ... fileN Dann können Sie diese einfach mit diesem Befehl verbinden

cat file* > output 

Fälle, in denen die Serie der verbundenen Dateien sein, die in alphabetischer Reihenfolge verbunden wurden.

+0

Dies funktioniert hervorragend für Textdateien. Wie wäre es mit den Binärdateien, die mit anderen Befehlen/Paketen/Software aufgeteilt wurden? –

+2

naja da hast du wohl irgendwas Header in jeder Datei was anzeigt, um was für eine Datei es geht, also gibt es das nicht ausreichend, aber du solltest nach anderen so fragen dafür suchen, ich bin mir sicher jemand hat es schon gelöst – rsz

+2

Die Frage ist um entsprechende Zeilen in den Eingabedateien zusammenzufügen. Nicht verketten sie. –

3

Ich habe eine Funktion dafür erstellt. Erstes Argument ist die Ausgabedatei, Restargumente sind die zu verbindenden Dateien.

function multijoin() { 
    out=$1 
    shift 1 
    cat $1 | awk '{print $1}' > $out 
    for f in $*; do join $out $f > tmp; mv tmp $out; done 
} 

Verbrauch:

multijoin output_file file* 
+0

Danke, das war nützlich. Wenn jemand den Header hinzufügen möchte, dann sed -i '1i header_text' output_file –