두 파일을 비교해야 하며 비교 결과에 따라 첫 번째 파일에 새 열을 추가해야 합니다. C 열은 기본 키입니다..
A,B,C,D
1,1990,I001,2473264
2,1991,I002,2473265
3,1992,I004,2473266
4,1993,6050,912432
5,1994,6003,912433
두 번째 파일
A,B
I001,2.3 GHz
I002,2.3 GHz
I004,2.3 GHz
6050,1.8 GHz
6003,850 MHz
예상 출력
A,B,C,D,E
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433
이 코드는 제대로 작동하지만 레코드가 일치하지 않으면 첫 번째 파일의 줄을 건너뜁니다. 하지만 건너뛰고 해당 열에 0 또는 NA를 추가하는 것을 원하지 않습니다.
awk -F, 'NR==FNR{a[$1]=$2;next}a[$3]{print $0","a[$3]}' test2 test1
A,B,C,D
1,1990,I001,2473264
2,1991,I002,2473265
3,1992,I004,2473266
4,1993,6050,912432
5,1994,6003,912433
6,1995,6004,21234
예상 출력:
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
답변1
awk
다음으로 변경하세요 .
$ awk -F, 'NR==FNR{a[$1]=$2;next} FNR!=1{print $0","(a[$3]?a[$3]:"NA")}' SECOND FIRST
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,NA
처음으로 원하는 결과를 얻으려면:
$ awk -F, 'NR==FNR{a[$1]=$2;next} FNR!=1{$3=(a[$3]?a[$3]:"NA")","$3; print}' OFS=, SECOND FIRST
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433
6,1995,NA,6004,21234
답변2
awk
귀하의 프로그램을 다음과 같이 수정하면 올바른 것입니다.무조건사용
print $0","( a[$3] ? a[$3] : 0 )
사용하는 대신
print $0","a[$3]
a[$3]
0이 아니거나 비어 있는 경우 . 즉, a[$3]
필드가 0이거나 비어 있으면 0을 사용하고, 그렇지 않으면 를 사용합니다 a[$3]
.
다시 말해서,
awk -F, -v OFS=',' 'FNR==NR { a[$1]=$2; next } FNR > 1 { print $0, (a[$3] ? a[$3] : 0) }' fileB fileA
FNR > 1
여기서는 헤더를 건너뛰는 데 사용합니다 .
사용 join
:
$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 fileA fileB
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
파일이 조인 키로 정렬되지 않은 경우(프로세스 대체를 지원하는 셸에서):
$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
4,1993,6050,912432,1.8 GHz
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
작업은 두 파일 모두에서 수행됩니다 join
. 쉼표가 필드 구분 기호임을 INNER JOIN
알려줌으로써 -t ,
세 번째 필드를 첫 번째 파일의 조인 키로 선택합니다( 해당 파일에서 동일한 다른 필드를 사용하지 않는 한 두 번째 파일의 첫 번째 필드가 키라고 가정 ).join
-1 3
-2 N
N
이 -o
플래그는 join
출력에 포함할 필드와 파일( x.y
파일의 열을 나타냄)을 알려줍니다.y
x
join
매우 빠른 작업이지만필요입력 파일은 조인 키를 기준으로 정렬됩니다(위의 첫 번째 예를 볼 수 있는 행운이 있었습니다). 위 두 번째 예의 최종 출력은 정렬되지 않았습니다.첫 번째필드이지만 파이프를 통해 쉽게 해결할 수 있습니다 sort -k1,1n
.
두 번째 경우에는 불일치로 인해
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -a 1 -e 0 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
4,1993,6050,912432,1.8 GHz
A,B,C,D,0
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
추가함으로써 첫 번째 파일의 모든 필드가 항상 출력되고 두 번째 파일의 각 누락된 필드에 0이 삽입되도록 -a 1 -e 0
요청합니다 .join
(-a 1
보시다시피 이제 올바른 결과를 얻었지만 (우리가 요청했기 때문에) 첫 번째 파일의 헤더도 포함했습니다. 두 파일의 데이터에서 헤더를 제거하고 결과를 정렬하려면 다음을 수행하십시오.
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -e 0 -a1 <( tail -n +2 fileA | sort -t, -k3,3 ) <( tail -n +2 fileB | sort ) | sort -k1,1n
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
이 명령은 실제로 두 상황 모두에 적용됩니다.
답변3
사용암소 비슷한 일종의 영양 join
확장된 데이터와첫 번째echo
헤더를 대체하기 위한 출력 형식 tail
( join
일관되지 않은 헤더로 인해 혼동될 수 있으므로):
echo A,B,C,D,E
join -t ',' --header --nocheck-order test1 test2 \
-a 1 -e NA -1 3 -2 1 -o 1.1,1.2,2.2,1.3,1.4 | tail -n +2
산출:
A,B,C,D,E
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433
6,1995,NA,6004,21234