두 파일을 awk와 결합


9

File1.txt

item1   carA
item2   carB
item3   carC
item4   platD
item5   carE

File2.txt

carA  platA
carB  platB
carC  platC
carE  platE

원하는 출력 :

item1   platA
item2   platB
item3   platC
item4   platD
item5   platE

어떻게하니?

답변:


11

아래 답변은 SO비슷한 Q & A를 기반으로하며 일부 관련 수정 사항이 있습니다.

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($2 in dict) ? dict[$2] : $2}1' file2.txt file1.txt 
item1 platA
item2 platB
item3 platC
item4 platD
item5 platE

아이디어는 인덱스가있는 해시 맵을 만들고 사전으로 사용하는 것입니다.

두 번째 질문에 대해 귀하의 의견에 요청했습니다 ( 의 두 번째 열이 file1.txt여섯 번째 열인 경우 어떻게 변경해야합니까 ).

입력 파일이 다음과 같은 경우 file1b.txt:

item1 A5 B C D carA
item2 A4 1 2 3 carB
item3 A3 2 3 4 carC
item4 A2 4 5 6 platD
item5 A1 7 8 9 carE

다음 명령이이를 수행합니다.

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($6 in dict) ? dict[$6] : $6;$3="";$4="";$5="";$6=""}1' file2.txt file1b.txt 
item1 platA    
item2 platB    
item3 platC    
item4 platD    
item5 platE    

1
@pawana-댓글에서 두 번째 질문을 해결하기 위해 답변을 업데이트했습니다. 귀하의 질문에 답변 한 경우 수락 하십시오.
Yaron

6

나는 당신이 말했다는 것을 알고 awk있지만, join이 목적을위한 명령이 있습니다 ...

{
  join -o 1.1,2.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt)     
  join -v 1 -o 1.1,1.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt) 
} | sort -k 1

join이 행이 아닌 경우 첫 번째 명령 으로 충분 합니다.

item4   platD

이 명령은 기본적으로 첫 번째 파일의 두 번째 열 ( -1 2)과 두 번째 파일의 첫 번째 열 ( )을 기반으로 결합하고 첫 번째 파일 의 첫 번째 열과 두 번째 파일의 두 번째 열 ( -2 1)을 출력합니다 -o 1.1,2.2. 페어링 된 라인 만 표시됩니다. 두 번째 조인 명령은 거의 같은 내용이지만, 페어링 할 수없는 첫 번째 파일의 행 ()을 표시하고 첫 번째 파일 -v 1의 첫 번째 열과 첫 번째 파일의 두 번째 열 ( )을 출력 한다고 합니다 -o 1.1,1.2. 그런 다음 두 출력을 결합하여 정렬합니다. sort -k 1첫 번째 열 sort -k 2을 기준으로 정렬을 의미하고 두 번째 열 을 기준으로 정렬하는 것을 의미합니다. 파일을 전달하기 전에 결합 열을 기준으로 파일을 정렬하는 것이 중요합니다 join.

이제 정렬을 두 번 작성했습니다. 도움이 될 수 있으면 디렉토리로 파일을 나누는 것을 좋아하지 않기 때문입니다. 그러나 데이비드 포스터 (David Foerster)가 말한 것처럼 파일의 크기에 따라 파일을 정렬 한 후 저장하여 두 번 정렬 할 때까지 기다리지 않을 수 있습니다. 크기에 대한 아이디어를주기 위해 다음은 내 컴퓨터에서 백만 줄과 천만 줄을 정렬하는 데 걸리는 시간입니다.

$ ruby -e '(1..1000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 1million.txt 
$ ruby -e '(1..10000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 10million.txt 
$ head 10million.txt 
item530284   plat530284
item7946579   plat7946579
item1521735   plat1521735
item9762844   plat9762844
item2289811   plat2289811
item6878181   plat6878181
item7957075   plat7957075
item2527811   plat2527811
item5940907   plat5940907
item3289494   plat3289494
$ TIMEFORMAT=%E
$ time sort 1million.txt >/dev/null
1.547
$ time sort 10million.txt >/dev/null
19.187

백만 줄의 경우 1.5 초, 천만 줄의 경우 19 초입니다.


이 경우 정렬되지 않은 크기의 데이터 세트에 대해 정렬이 오래 걸리기 때문에 정렬 된 입력 데이터를 (임시) 중간 파일에 저장하는 것이 좋습니다. 그렇지 않으면 +1입니다.
David Foerster

@David 좋은 지적입니다. 개인적으로, 나는 중간 파일을 생성하는 것을 싫어하지만, 오랫동안 실행되는 프로세스에 열심입니다. 나는 "사소한 크기"가 무엇인지 궁금해해서 작은 벤치 마크를 만들고 제안과 함께 답변에 추가했습니다.
JoL

현대의 데스크탑 컴퓨터에서는 1 mio 레코드를 정렬하는 것이 충분히 빠릅니다. 2 개 이상의 3 배 크기로 더 많은 것들이 흥미로워지기 시작합니다. 어쨌든 경과 시간 (실시간) ( %E시간 형식)은 계산 성능을 측정하는 데 덜 흥미 롭습니다. 사용자 모드 CPU 시간 ( %U또는 단순히 설정되지 않은 TIMEFORMAT변수)이 훨씬 더 의미가 있습니다.
David Foerster

@David 저는 다른 시대의 유스 케이스에 익숙하지 않습니다. 왜 더 흥미로운가요? 경과 시간은 실제로 기다리는 시간과 일치합니다. 1.5 초 명령의 경우 4.5 초가 나타납니다 %U.
JoL

1
경과 시간은 동일한 시스템에서 실행중인 다른 작업을 대기하고 I / O 요청을 차단하는 데 소요 된 시간의 영향을받습니다. (사용자) CPU 시간이 아닙니다. 일반적으로 계산 바운드 알고리즘의 속도를 비교할 때 I / O를 무시하고 다른 백그라운드 작업으로 인한 측정 오류를 피하려고합니다. 중요한 질문은 "이 알고리즘이 해당 데이터 세트에서 얼마나 많은 계산을 요구합니까?"입니다. "컴퓨터가 계산이 완료되기를 기다리는 동안 모든 작업에 시간이 얼마나 걸렸습니까?"
David Foerster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.