Scal pliki przy użyciu wspólnej kolumny

8

Mam dwa pliki, z których chcę utworzyć trzeci, który zawiera wszystkie informacje.

plik 1:

a 111 
b 222 
c 333 
d 666 
e 777 

plik 2:

111 x1  
222 x2
333 x3
444 x4 
555 x5 
666 x6 
777 x7 
888 x8

Chciałbym je połączyć w następujący sposób:

111  x1  a
222  x2  b
333  x3  c
444  x4  0
555  x5  0
666  x6  d
777  x7  e
888  x8  0

Uwaga:

Druga kolumna pliku 1 jest podzbiorem pierwszej kolumny pliku 2

gforce89
źródło

Odpowiedzi:

7

joinKomenda robi prawie to, czego potrzebujesz, jeśli pliki są klasyfikowane jako w swoim próbek:

join -12 -a2 file1 file2 -o2.1,2.2,1.1

Musisz tylko dodać zera do linii bez dopasowania. Możesz użyć do tego -eprzełącznika:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0
choroba
źródło
jeśli dodasz -e0, nie potrzebujesz perla :)
LilloX
@LilloX: To prawda, dziękuję. Próbowałem, ale nie powiodło się (literówka).
choroba
13

Za pomocą dołączenia:

join -1 1 -2 2 -a1 -e0 -o'0,1.2,2.1' file2 file1

Polecenie join łączy linie dwóch plików, które mają wspólne pole danych. W takim przypadku: Połącz plik 2 i plik 1, używając pola 1 ( -1 1) pliku 2 i pola 2 ( -2 2) pliku 1.

Dane wyjściowe to: „pole połączone, pole 2 pliku 2, pole 1 pliku 1” ( -o'0,1.2,2.1'), jeśli brakuje pola, wpisz 0 ( -e0)

Jeśli jeden z dwóch plików ma więcej rekordów, dodaj je (w tym przypadku file2) ( -a1)

Proszę odnieść się do strony manuala polecenia join

LilloX
źródło
Dobrze. Czy możesz dodać trochę wyjaśnienia?
Lety,
Pewnie, zaktualizowano :)
LilloX,
5

Trochę awkmagii:

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0}; \
    printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}' \
    file1 file2

lub

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

Wynik

111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Wyjaśnienie

  • FNR==NR{a[$2]=$1;next}

    Uruchamia file1( FNR==NR) i tworzy strukturę klucz-wartość. Klucz to druga kolumna ( $2) z file1, wartość to pierwsza kolumna ( $1) zfile1

  • {if(a[$1]==""){a[$1]=0};print $1,$2,a[$1]}

    Działa file2i

    • if(a[$1]==""){a[$1]=0}

      Jeśli klucz w pierwszej kolumnie ( $1) w file2nie istnieje file1, potrzebujemy0

    • print $1,$2,a[$1]

      Wydrukuj (używając print) pierwszą i drugą kolumnę file2oraz wartość struktury klucz-wartość za pomocą klucza pierwszej kolumny ( $1)file2

      lub

    • printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}'

      Wydrukuj (używając printf) pierwszą i drugą kolumnę file2oraz wartość struktury klucz-wartość za pomocą klucza pierwszej kolumny ( $1) z file2.

      • FS to separator między kolumnami pobrany z pliku wejściowego

      • "%s%s%s%s%s\n"

        jest formatowaniem danych wyjściowych

        • %s - Strunowy

        • \n - Nowa linia

AB
źródło
Czy możesz wyjaśnić kod?
gforce89
Jasne, odpowiedź zaktualizowana.
AB
1

Używając q :

$ q "select f2.c1, f2.c2, ifnull(f1.c1,0) from file_2.txt f2 LEFT JOIN file_1.txt f1 on f1.c2 = f2.c1 "
111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Czasami może być bardziej czytelny.

Vi.
źródło
1
Dla każdego, kto się zastanawia, qjest w pakiecie python3-q-text-as-data(Python 3) i w pakiecie python-q-text-as-data(Python 2).
Kos
Dzięki, ale gdzie mogę dostać ten qpakiet? I nie wydaje się, aby móc zainstalować albo python-q-text-as-dataalbo python3-q-text-as-data. „E: Nie można znaleźć pakietu python3-q-text-as-data”. Mój system już został zainstalowany python, python2.7, python3, i python3.4.
Paddy Landau,
Być może pakiet jest zbyt nowy i nie jest dostępny w twojej wersji dystrybucyjnej. Możesz go sklonować Github: github.com/harelba/q
Vi.