저는 유닉스를 처음 사용하는데(일주일만 지났습니다) 파일 두 개에 문제가 있습니다
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;}
이 파일은 이전 파일이 실행되고 있지 않고 두 번째 파일을 읽는 경우에만 실행됩니다. 배열에 저장한다는 점을 제외하면 두 번째 파일의 값과 동일한 작업을 수행합니다 b
.
모든 입력이 끝나면 블록 END{}
이 실행됩니다. 이것은 in에 있는 모든 키에 대해 반복되며 a
, in에 있는 키이기도 하고 b
해당 값이 동일하지 않으면 키를 인쇄합니다.