Xử lý hai tệp bằng awk


9

Tôi đọc So sánh hai tệp bằng Unix và Awk . Nó thực sự thú vị. Tôi đã đọc và kiểm tra nó, nhưng tôi không thể hiểu nó hoàn toàn và sử dụng nó trong các trường hợp khác.

Tôi có hai tập tin. file1có một lĩnh vực và một lĩnh vực khác có 16 lĩnh vực. Tôi muốn đọc các phần tử của file1 và so sánh chúng với trường thứ 3 của file2. Nếu có một kết quả khớp cho mỗi phần tử, tôi tính tổng giá trị của trường 5 trong file2. Ví dụ:

tập tin 1

1
2
3

tập tin 2

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

Đối với phần tử 1 trong file1tôi muốn thêm các giá trị trong trường 5 trong file2đó giá trị của trường 3 là 1. Và thực hiện tương tự cho phần tử 2 và 3 trong file1. Đầu ra cho 1 là (3 + 4 = 7) và cho 2 là 2 và cho 3 là 4.

Tôi không biết làm thế nào tôi nên viết nó với awk.

Câu trả lời:


20

Đây là một cách. Tôi đã viết nó dưới dạng một kịch bản awk để tôi có thể thêm ý kiến:

#!/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];
    }
}

Bạn có thể lưu nó dưới dạng một tệp, làm cho nó có thể thực thi được và chạy nó như vậy:

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

Hoặc, bạn có thể ngưng tụ nó thành một lớp lót:

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

9
awk '
  NR == FNR {n[$3] += $5; next}
  {print $1 ": " n[$1]}' file2 file1

Nó thực hiện một số công việc bổ sung bằng cách tóm tắt các trường không khớp.
Emmanuel

@Emmanuel, đó vẫn là một hướng dẫn tuyệt vời cho mỗi dòng của tệp 2, làm cho nó ngắn hơn và nhanh hơn terdon
Stéphane Chazelas

giải pháp sáng chói!
Ronald Pauffert
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.