匹配输入与输出文件中的数据

匹配输入与输出文件中的数据

我是 unix 新手(刚接触一周),我遇到问题,有两个文件

2|1019|0|12 
2|1019|3|0 
2|1021|0|2 
2|1021|2|0 
2|1022|4|5
2|1030|0|1 
2|1030|5|0 
2|1031|4|4

2|1019|0|12 
2|1019|3|10 
2|1021|0|22 
2|1021|2|0 
2|1022|4|15

一个是输出文件,另一个是输入文件

如果第 2 列中的值匹配,我想将两行的第 3 列和第 4 列中的值相加,否则只需将输入和输出的唯一行中的第 3 列和第 4 列中的值相加,然后比较总计(第 3 和第 4)并且如果存在差异,则会引发一条消息,其中第二列的值与总和不匹配

总数是

1019 15
1021 4
1022 9
1030 6
1031 8

在输入中

总数是

1019 25
1021 24
1022 19

在输出中

Expected output 
Unequal total for 1019,1021,1022

注意:输入和输出中的值是用管道(|)分隔的

运行这个脚本

awk -F '|' '{Arr[$2]=Arr[$2]+$3+$4}END{ for(i in Arr)print "amount for planId " i " is :"Arr[i]}'

在第一个文件上并得到这个输出

amount for planId  is :0
amount for planId 1019 is :12
amount for planId 1021 is :4
amount for planId 1022 is :9
amount for planId 1030 is :6
amount for planId 1031 is :8

不知道为什么第一行出现

amount for planId  is :0

答案1

前 2 个 awk 命令用于添加值并将输出重定向到 f1.out 和 f2.out

最后一个是比较 f1.out 和 f2.out 之间的值

$ awk '{Arr[$2]=Arr[$2]+$3+$4}END{for(i in Arr)print i,Arr[i]}' file1 > f1.out
$ awk '{Arr[$2]=Arr[$2]+$3+$4}END{for(i in Arr)print i,Arr[i]}' file2 > f2.out
$ awk 'NR==FNR{Arr[$1]=$2;next}{if(Arr[$1]!=$2){out=$1","out;}}END{print out}' f1.out f2.out

答案2

另一种awk方法:

$ awk 'NR==FNR{a[$2]+=$3+$4; next} {b[$2]+=$3+$4;}
       END{
           for(i in a){
             if(i in b && a[i]!=b[1]){
                print "Unequal total for",i
             }
           }
       }' input output 
Unequal total for 1019
Unequal total for 1021
Unequal total for 1022

或者,如果您确实需要问题中显示的确切输出:

$ awk 'NR==FNR{a[$2]+=$3+$4; next} {b[$2]+=$3+$4;}
       END{
            for(i in a){
                if(i in b && a[i]!=b[1]){
                    c[i]
                }
            } 
            printf "Unequal total for "; 
            for(i in c){printf "%s, ", i}
        }' input output | perl -pe 's/,\s*$/\n/'
Unequal total for 1019, 1021, 1022

FNR是当前文件的行号,也是NR所有输入的总行号。仅当读取第一个文件时两者才相等。因此,NR==FNR{a[$2]+=$3+$4; next}会将第三列和第四列的总和添加到与数组中第二列关联的值a,并且仅对第一个文件执行此操作。这next确保我们移动到下一行并且不执行当前行的脚本的其余部分。

{b[$2]+=$3+$4;}仅当前一个文件未运行且我们正在读取第二个文件时,该文件才会运行。它对第二个文件中的值执行相同的操作,只不过它将它们保存在 array 中b

一旦我们到达所有输入的末尾,该END{}块就会被执行。这将迭代 in 中的所有键a,如果它们也是 in 中的键b,并且它们的值不相同,则会打印出该键。

相关内容