กำลังประมวลผลสองไฟล์โดยใช้ awk


9

ผมอ่านเปรียบเทียบสองไฟล์โดยใช้ Unix และ Awk มันน่าสนใจจริงๆ ฉันอ่านและทดสอบ แต่ไม่สามารถเข้าใจได้อย่างสมบูรณ์และใช้ในกรณีอื่น

ฉันมีสองไฟล์ file1มีหนึ่งฟิลด์และอีกฟิลด์หนึ่งมี 16 ฟิลด์ ฉันต้องการที่จะอ่านองค์ประกอบของfile1 file2และเปรียบเทียบกับข้อมูลที่ หากมีการแข่งขันสำหรับแต่ละองค์ประกอบ, I คุ้มค่าผลรวมของสนามที่ 5 file2ใน ตัวอย่างเช่น:

ไฟล์ 1

1
2
3

ไฟล์ 2

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

สำหรับองค์ประกอบ 1 ในfile1ฉันต้องการที่จะเพิ่มค่าในสาขาที่ 5 ของfile2ที่มีค่าของเขต 3 เป็น 1 และทำเช่นเดียวกันสำหรับองค์ประกอบที่ 2 และ 3 file1ใน เอาต์พุตสำหรับ 1 คือ (3 + 4 = 7) และสำหรับ 2 คือ 2 และสำหรับ 3 คือ 4

ฉันไม่รู้ว่าฉันควรเขียนด้วย awk อย่างไร

คำตอบ:


20

นี่คือวิธีหนึ่ง ฉันเขียนเป็นสคริปต์ awk เพื่อให้ฉันสามารถเพิ่มความคิดเห็น:

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

คุณสามารถบันทึกเป็นไฟล์ทำให้สามารถเรียกใช้และเรียกใช้ได้โดย:

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

หรือคุณสามารถรวมเข้าเป็นหนึ่งซับ:

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

มันทำงานพิเศษได้โดยการรวมฟิลด์ที่ไม่ตรงกัน
Emmanuel

@Emmanuel ยังคงมีหนึ่งคำสั่ง awk ต่อบรรทัดของ file2 ซึ่งทำให้สั้นกว่าและเร็วกว่า terdon's
Stéphane Chazelas

วิธีการแก้ปัญหาที่สดใส!
Ronald Pauffert
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.