두 파일을 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.