Gabungkan file menggunakan kolom umum

8

Saya memiliki dua file di mana saya ingin membuat yang ketiga yang berisi semua informasi.

file 1:

a 111 
b 222 
c 333 
d 666 
e 777 

file 2:

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

Saya ingin menggabungkan mereka sebagai berikut:

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

catatan:

Kolom kedua file 1 adalah subset dari kolom pertama file 2

gforce89
sumber

Jawaban:

7

The joinperintah melakukan hampir apa yang Anda butuhkan, jika file diurutkan seperti pada sampel Anda:

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

Anda hanya perlu menambahkan nol ke garis tanpa kecocokan. Anda dapat menggunakan -esakelar untuk itu:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0
choroba
sumber
jika Anda menambahkan -e0tidak perlu perl :)
LilloX
@LilloX: Benar, terima kasih. Saya mencoba tetapi gagal (salah ketik).
choroba
13

Menggunakan join:

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

Perintah join bergabung dengan garis dua file yang berbagi bidang data yang sama. Dalam hal ini: Bergabung dengan file2 dan file1 menggunakan bidang 1 ( -1 1) dari file2 dan bidang 2 ( -2 2) dari file1.

Outputnya adalah: "bidang gabungan, bidang 2 file2, bidang 1 file1" ( -o'0,1.2,2.1'), jika ada bidang yang hilang cantumkan 0 ( -e0)

Jika salah satu dari dua file memiliki lebih banyak catatan maka tambahkan (dalam hal ini file2) ( -a1)

Silakan merujuk ke halaman manual dari perintah join

LilloX
sumber
Baik. Bisakah Anda menambahkan sedikit penjelasan?
Lety
Tentu, Diperbarui :)
LilloX
5

Sedikit awksihir:

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

atau

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

Keluaran

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

Penjelasan

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

    Jalankan file1( FNR==NR) dan buat struktur nilai kunci. Kuncinya adalah kolom kedua ( $2) dari file1, nilainya adalah kolom pertama ( $1) darifile1

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

    Berlari file2dan

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

      Jika kunci pada kolom pertama ( $1) di file2tidak ada file1, kita perlu a0

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

      Cetak (menggunakan print) kolom pertama dan kedua file2dan nilai struktur nilai kunci dengan kunci kolom pertama ( $1) darifile2

      atau

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

      Cetak (menggunakan printf) kolom pertama dan kedua file2dan nilai struktur nilai kunci dengan kunci kolom pertama ( $1) dari file2.

      • FS adalah pemisah antara kolom, yang diambil dari file input

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

        adalah format untuk output

        • %s - Tali

        • \n - Garis baru

AB
sumber
Bisakah Anda menjelaskan kodenya?
gforce89
Tentu, jawab diperbarui.
AB
1

Menggunakan 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

Mungkin lebih mudah dibaca dengan cara ini.

Vi.
sumber
1
Untuk siapa pun yang bertanya-tanya, qada dalam paket python3-q-text-as-data(Python 3) dan dalam paket python-q-text-as-data(Python 2).
kos
Terima kasih, tetapi dari mana saya bisa mendapatkan qpaket ini ? Saya sepertinya tidak dapat menginstal salah satu python-q-text-as-dataatau python3-q-text-as-data. "E: Tidak dapat menemukan paket python3-q-text-as-data". Sistem saya sudah telah terinstal python, python2.7, python3, dan python3.4.
Paddy Landau
Mungkin paket itu terlalu baru dan tidak tersedia dalam rilis distribusi Anda. Anda dapat mengkloningnya Github: github.com/harelba/q
Vi.