GNU/Linux >> Belajar Linux >  >> Linux

Bergabung dengan banyak bidang dalam file teks di Unix

Mungkin paling mudah menggabungkan tiga kolom pertama dengan awk:

awk '{print $1 "_" $2 "_" $3 " " $4}' filename

Kemudian Anda dapat menggunakan join biasanya di "bidang 1"


Anda dapat mencoba ini

awk '{
 o1=$1;o2=$2;o3=$3
 $1=$2=$3="";gsub(" +","")
 _[o1 FS o2 FS o3]=_[o1 FS o2 FS o3] FS $0
}
END{ for(i in _) print i,_[i] }' file1 file2

keluaran

$ ./shell.sh
foo 1 scaf  3 4.5
bar 2 scaf  3.3 1.00
foo 1 boo  2.3

Jika Anda ingin menghilangkan baris yang tidak biasa

awk 'FNR==NR{
 s=""
 for(i=4;i<=NF;i++){ s=s FS $i }
 _[$1$2$3] = s
 next
}
{
  printf $1 FS $2 FS $3 FS
  for(o=4;o<NF;o++){
   printf $i" "
  }
  printf $NF FS _[$1$2$3]"\n"
 } ' file2 file1

keluaran

$ ./shell.sh
foo 1 scaf 3  4.5
bar 2 scaf 3.3  1.00

Inilah yang benar answer (dalam hal menggunakan GNU coreutils standar alat, dan tidak menulis skrip khusus di perl/awk sebut saja).

$ join -j1 -o1.2,1.3,1.4,1.5,2.5 <(<file1 awk '{print $1"-"$2"-"$3" "$0}' | sort -k1,1) <(<file2 awk '{print $1"-"$2"-"$3" "$0}' | sort -k1,1)
bar 2 scaf 3.3 1.00
foo 1 scaf 3 4.5

Oke, bagaimana cara kerjanya:

  1. Pertama-tama kita akan menggunakan alat hebat join yang dapat menggabungkan dua baris. join memiliki dua persyaratan:

    • Kita dapat bergabung hanya dengan satu kolom.
    • Kedua file harus diurutkan menurut kolom kunci!
  2. Kita perlu membuat kunci dalam file input dan untuk itu kami menggunakan awk sederhana skrip:

    $ cat file1
    foo 1 scaf 3
    bar 2 scaf 3.3    
    
    $ <file1 awk '{print $1"-"$2"-"$3" "$0}'
    foo-1-scaf foo 1 scaf 3
    bar-2-scaf bar 2 scaf 3.3
    

    Anda lihat, kami menambahkan kolom pertama dengan beberapa kunci seperti "foo-1-scaf ".Kami melakukan hal yang sama dengan file2 .OMONG-OMONG. <file awk , hanyalah cara penulisan yang bagus awk file , atau cat file | awk .

    Kita juga harus menyortir file kami dengan kunci, dalam kasus kami ini adalah kolom 1, jadi kami menambahkan | sort -k1,1 di akhir perintah (urutkan melalui teks dari kolom 1 ke kolom 1)

  3. Pada titik ini kita hanya dapat membuat file file1.with.key dan file2.with.key dan bergabunglah dengan mereka, tetapi misalkan file itu sangat besar, kami tidak ingin menyalinnya melalui sistem file. Sebagai gantinya, kita dapat menggunakan sesuatu yang disebut bash substitusi proses untuk menghasilkan output ke pipa bernama (ini akan menghindari pembuatan file perantara yang tidak perlu). Untuk info lebih lanjut, silakan baca tautan yang disediakan.

    Sintaks target kami adalah:join <( some command ) <(some other command)

  4. Hal terakhir adalah menjelaskan argumen gabungan yang mewah:-j1 -o1.2,1.3,1.4,1.5,2.5

    • -j1 - gabung dengan kunci di kolom pertama (di kedua file)
    • -o - hanya menampilkan bidang-bidang itu 1.2 (kolom file ke-12), 1.3 (file pertama kolom 3), dll.

      Dengan cara ini kita menggabungkan baris, tetapi join hanya menampilkan kolom yang diperlukan.

Pelajaran yang dapat dipetik dari postingan ini adalah:

  • Anda harus menguasai coreutils paket, alat tersebut sangat andal jika digabungkan dan Anda hampir tidak perlu menulis program khusus untuk menangani kasus seperti itu,
  • Alat utils inti juga sangat cepat dan teruji, sehingga selalu menjadi pilihan terbaik.

Perintah gabung sulit digunakan dan hanya bergabung pada satu kolom

Eksperimen ekstensif ditambah pengawasan ketat terhadap halaman manual menunjukkan bahwa Anda tidak dapat langsung menggabungkan beberapa kolom - dan semua contoh kerja saya tentang bergabung, lucunya, gunakan hanya satu kolom bergabung.

Akibatnya, solusi apa pun akan membutuhkan kolom yang akan digabungkan untuk digabungkan menjadi satu kolom, entah bagaimana caranya. Perintah gabung standar juga memerlukan inputnya dalam urutan terurut yang benar - ada komentar di gabungan GNU (info coreutils join) tentang hal itu tidak selalu membutuhkan data yang diurutkan:

Namun, sebagai ekstensi GNU, jika input tidak memiliki baris yang tidak dapat dipasangkan, urutan pengurutan dapat berupa urutan apa pun yang menganggap dua bidang sama jika dan hanya jika perbandingan pengurutan yang dijelaskan di atas menganggapnya sama.

Salah satu cara yang mungkin untuk melakukannya dengan file yang diberikan adalah:

awk '{printf("%s:%s:%s %s %s %s %s\n", $1, $2, $3, $1, $2, $3, $4);}' file1 |
sort > sort1
awk '{printf("%s:%s:%s %s %s %s %s\n", $1, $2, $3, $1, $2, $3, $4);}' file2 |
sort > sort2
join -1 1 -2 1 -o 1.2,1.3,1.4,1.5,2.5 sort1 sort2

Ini membuat bidang pengurutan gabungan di awal, menggunakan ':' untuk memisahkan sub-bidang, lalu mengurutkan file - untuk masing-masing dari dua file. Perintah gabung kemudian menggabungkan dua bidang komposit, tetapi hanya mencetak bidang non-komposit (non-gabung).

Outputnya adalah:

bar 2 scaf 3.3 1.00
foo 1 scaf 3 4.5

Upaya yang gagal untuk membuat bergabung melakukan apa yang tidak akan dilakukan

gabung -1 1 -2 1 -1 2 -2 2 -1 3 -2 3 -o 1.1,1.2,1.3,1.4,2.4 file1 file2

Di MacOS X 10.6.3, ini memberikan:

$ cat file1
foo 1 scaf 3 
bar 2 scaf 3.3
$ cat file2
foo 1 scaf 4.5
foo 1 boo 2.3
bar 2 scaf 1.00
$ join -1 1 -2 1 -1 2 -2 2 -1 3 -2 3 -o 1.1,1.2,1.3,1.4,2.4 file1 file2
foo 1 scaf 3 4.5 
bar 2 scaf 3.3 4.5 
$

Ini bergabung di bidang 3 (hanya) - yang bukan itu yang diinginkan.

Anda perlu memastikan bahwa file input berada dalam urutan yang benar.


Linux
  1. Dd:Beberapa File Input?

  2. Bagaimana cara membagi satu file teks menjadi beberapa file *.txt?

  3. Bergabunglah dengan banyak file MP3 (tanpa kerugian)

  1. Impor Beberapa File SQL Di MySQL

  2. Cara Membuat Zip Banyak File di Linux

  3. Bagaimana cara mengganti nama banyak file dalam satu perintah atau skrip di Unix?

  1. Cara Menggabungkan Dua File Teks di Linux

  2. Bagaimana Cara Mengganti Nama Banyak File Dalam Satu Perintah Atau Skrip Di Unix??

  3. Bagaimana Cara Mengganti Nama Banyak File Menggunakan Find?