Memproses dua file menggunakan awk

9

Saya membaca Membandingkan dua file menggunakan Unix dan Awk . Sangat menarik. Saya membaca dan mengujinya, tetapi saya tidak dapat memahaminya sepenuhnya dan menggunakannya dalam kasus lain.

Saya punya dua file. file1memiliki satu bidang dan yang lainnya memiliki 16 bidang. Saya ingin membaca elemen file1 dan membandingkannya dengan bidang ke-3 file2. Jika ada kecocokan untuk setiap elemen, saya menjumlahkan nilai bidang 5 in file2. Sebagai contoh:

file 1

1
2
3

file 2

2 2 2 1 2
3 6 1 2 4 
4 1 1 2 3
6 3 3 3 4 

Untuk elemen 1 di file1saya ingin menambahkan nilai di bidang 5 di file2mana nilai bidang 3 adalah 1. Dan melakukan hal yang sama untuk elemen 2 dan 3 in file1. Output untuk 1 adalah (3 + 4 = 7) dan untuk 2 adalah 2 dan untuk 3 adalah 4.

Saya tidak tahu bagaimana saya harus menulisnya dengan awk.

pengguna55340
sumber

Jawaban:

20

Ini satu cara. Saya telah menulisnya sebagai skrip awk sehingga saya dapat menambahkan komentar:

#!/usr/local/bin/awk -f

{
    ## FNR is the line number of the current file, NR is the number of 
    ## lines that have been processed. If you only give one file to
    ## awk, FNR will always equal NR. If you give more than one file,
    ## FNR will go back to 1 when the next file is reached but NR
    ## will continue incrementing. Therefore, NR == FNR only while
    ## the first file is being processed.
    if(NR == FNR){
      ## If this is the first file, save the values of $1
      ## in the array n.
      n[$1] = 0
    }
    ## If we have moved on to the 2nd file
    else{
      ## If the 3rd field of the second file exists in
      ## the first file.
      if($3 in n){
        ## Add the value of the 5th field to the corresponding value
        ## of the n array.
        n[$3]+=$5
      }
    }
}
## The END{} block is executed after all files have been processed.
## This is useful since you may have more than one line whose 3rd
## field was specified in the first file so you don't want to print
## as you process the files.
END{
    ## For each element in the n array
    for (i in n){
    ## print the element itself and then its value
    print i,":",n[i];
    }
}

Anda dapat menyimpannya sebagai file, membuatnya dapat dieksekusi dan menjalankannya seperti ini:

$ chmod a+x foo.awk
$ ./foo.awk file1 file2
1 : 7
2 : 2
3 : 4

Atau, Anda bisa memadatkannya menjadi satu garis:

awk '
     (NR == FNR){n[$1] = 0; next}
     {if($3 in n){n[$3]+=$5}}
     END{for (i in n){print i,":",n[i]} }' file1 file2
terdon
sumber
9
awk '
  NR == FNR {n[$3] += $5; next}
  {print $1 ": " n[$1]}' file2 file1
Stéphane Chazelas
sumber
Itu melakukan beberapa pekerjaan ekstra dengan menjumlahkan bidang yang tidak cocok.
Emmanuel
@Emmanuel, itu masih satu instruksi awk per baris file2, yang membuatnya lebih pendek dan lebih cepat daripada terdon
Stéphane Chazelas
solusi cemerlang!
Ronald Pauffert