2012-05-23 22 views
9

Używam standardowego polecenia łączenia, aby połączyć dwa posortowane pliki na podstawie kolumny 1. Polecenie jest proste dołącz file1 file2> output_file.dołącz wiele plików

Ale jak mogę dołączyć 3 lub więcej plików przy użyciu tej samej techniki? dołącz plik1 file2 file3> output_file Powyższe polecenie dało mi pusty plik. Myślę, że sed może mi pomóc, ale nie jestem zbyt pewny jak?

Odpowiedz

19

man join:

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

SYNOPSIS 
     join [OPTION]... FILE1 FILE2 

działa tylko z dwa plików.

Jeśli chcesz dołączyć do trzech, może najpierw dołącz do dwóch pierwszych, a następnie dołącz do trzeciego.

try:

join file1 file2 | join - file3 > output 

że powinien dołączyć do trzech plików bez tworzenia pliku pośredniego temp. - mówi polecenie dołączenia do zapoznania się z pierwszym wejściem strumienia z stdin

+0

co masz na myśli przez łącznik do drugiego łączenia ?? czy jest to specjalny symbol łączenia? –

+0

zobacz moją aktualizację. '-' jest rozumiany przez wiele programów unix jako skrót dla stdin/stdout – mata

+0

. dzięki. –

0

Połącz dołącza do linii dwa pliki na wspólnym polu. Jeśli chcesz dołączyć więcej - zrób to parami. Najpierw dołącz najpierw dwa pierwsze pliki, następnie dołącz wynik do trzeciego pliku itp.

2

Strona man z join stwierdza, że ​​działa tylko dla dwóch plików. Więc trzeba tworzyć i plik pośredni, którego potem usunąć, tj .:

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

lub 'przyłączyć <(join plik1 plik2) file3' – Kevin

+0

@Kevin słodkie! Nie wiedziałem tego! – Gnosophilon

9

można połączyć wiele plików (n> = 2) poprzez budowę rurociągu join s rekurencyjnie:

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

Zdecydowanie moja ulubiona odpowiedź!Jednak zastąpiłem ciało funkcji 'join_rec' następująco:' f1 = $ 1; f2 = 2 USD; przesunięcie 2; , jeśli [$ # -gt 0]; następnie; dołącz "$ f1" "$ f2" | join_rec - "$ @"; else; dołącz "$ f1" "$ f2"; fi', aby wyeliminować potrzebę drugiego 'if'. Wywołanie będzie wyglądało jak "join_rec" $ @ "' – user43791

+0

@ack Czy jest możliwe dodanie nazwy pliku jako nagłówka w danych wyjściowych? – user1883491

7

wiem, że to jest stary pytanie, ale na przyszłość. Jeśli wiesz, że pliki, które chcesz dołączyć, mają wzór podobny do tego w pytaniu tutaj, np. file1 file2 file3 ... fileN Następnie można po prostu połączyć je z tym poleceniem

cat file* > output 

Jeżeli wyjście zostanie seria połączonych plików, które zostały połączone w kolejności alfabetycznej.

+0

Działa to znakomicie dla plików tekstowych. Co powiesz na pliki binarne, które zostały podzielone za pomocą innych poleceń/pakietów/oprogramowania. –

+2

cóż, masz prawdopodobnie nagłówek w każdym pliku, który wskazuje, jaki to plik, więc nie jest to wystarczające, ale powinieneś poszukać innych, więc na to pytanie, jestem pewien, że ktoś już to rozwiązał. – rsz

+2

Pytanie jest aby połączyć ze sobą odpowiednie wiersze w plikach wejściowych. Nie łącząc ich. –

3

Stworzyłem dla tego funkcję. Pierwszy argument to plik wyjściowy, a pozostałe argumenty to pliki, które mają zostać połączone.

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

Zastosowanie:

multijoin output_file file* 
+0

Dzięki, to było przydatne. jeśli ktoś chce dodać nagłówek, to sed -i '1i header_text' output_file –

Powiązane problemy