순서를 방해하지 않고 여러 필드가 있는 CSV에 참여

순서를 방해하지 않고 여러 필드가 있는 CSV에 참여

2개의 CSV 파일이 있습니다. 첫 번째 파일은 크기가 크며(400개 이상의 필드, 많은 행이 100만 개 이상) 일치 조인을 통해 다른 필드를 추가해야 합니다.

나는 분야에 참여하고 싶습니다$170

나는 열심히 노력했다

gawk 'BEGIN {OFS=FS=","} NR==FNR{b[$1]=$2; next} 
$170 in b {print $0,b[$170]}
' b a

보고서에 따르면 이 방법은 잘 작동하지만 파일 크기가 커지면 문제가 발생할 수 있습니다. 이 awk 명령이 완전한 외부 조인을 수행하지 않는 이유는 무엇입니까?(@cuonglm의 답변 참조)

아직 테스트하지는 않았지만 파일 크기가 증가함에 따라 "최상의" 접근 방식을 알고 싶습니다.

@cuonglm이 제안했지만 join이는 연결된 필드를 먼저 배치하도록 열을 재정렬합니다.
매우 길기 때문에 인수를 사용하여 명령에 대한 긴 출력 형식을 쉽게 작성할 수 없습니다 .join-o

join -1 170 -2 1 -o1.1 1.2 1.3 1.4......1.300.... file1 file2

join이 작업을 더 쉽게 수행할 수 있는 방법이 있나요 ?

gawk아니면 파일 크기 문제 때문에 이를 고수해야 합니까 (예를 들어 파일 a와 b에 최대 500만 개의 행이 있고 둘 다 약 500개의 열이 있음)?

답변1

전체 너드 테스트를 해봤습니다. 500만행×500열(20GB)의 CSV와 500만행×2열의 보조파일을 만들었습니다. 키 필드는 고유하며(5백만 개의 소수가 있음) 빅 파일의 열 170과 사이드 파일의 열 1에 있습니다. 두 파일 모두 독립적으로 무작위로 추출된 키 시퀀스를 포함합니다. 다른 모든 필드에는 약 14,000단어(맨 페이지에서 추출)에서 무작위로 선택된 항목이 포함되어 있습니다.

awk 스크립트는 거의 20분 동안 실행되었습니다.전체 프로세스는 약 0.8GB의 메모리를 사용합니다.. 이것은 4GB 노트북과 5400rpm 하드 드라이브에 있습니다. 로그에는 시간, 파일 크기, 열 수가 표시됩니다.

Paul--) time ./datMerge

real    18m31.740s
user    10m21.632s
sys 1m48.316s
Paul--) wc -lc *max*
    5061456 20045559105 FileA.max.csv
    5061456    85634275 FileB.max.csv
    5061456 20085640276 FileC.max.csv
   15184368 40216833656 total
Paul--) for f in F*max*; do
> awk '-F,' '{ printf ("%8d %s\n", NF, FILENAME); }' "${f}"
> done | uniq -c
5061456      500 FileA.max.csv
5061456        2 FileB.max.csv
5061456      501 FileC.max.csv
Paul--) ls -l F*max*
-rw-r--r-- 1 paul paul 20045559105 Feb  8 19:49 FileA.max.csv
-rw-r--r-- 1 paul paul    85634275 Feb  8 19:49 FileB.max.csv
-rw-r--r-- 1 paul paul 20085640276 Feb  8 20:24 FileC.max.csv
Paul--) 

나는 6행과 6열의 기능을 보여주기 위해 파일의 미니 버전을 만들었습니다. 키는 4열에 있습니다.

Paul--) head F*mini*
==> FileA.mini.csv <==
rather,complies,finite,99999847,AM,Or
elapsed,plied,nearperfect,99999989,pr,WinChip
phiopt,reflects,bottom,99999959,128N,careful
fpackstructn,realworld,msingleexit,99999931,0xffff,maxmimum
simplified,mpopcntb,FrontCover,99999971,523x,requisite
cede,fdumprtlbtl2,atmega649a,99999941,LC_MESSAGES,errno

==> FileB.mini.csv <==
99999847,symbols
99999931,fdumprtldbr
99999959,ambiguous
99999971,crc
99999989,munsafedma

==> FileC.mini.csv <==
rather,complies,finite,99999847,AM,Or,symbols
elapsed,plied,nearperfect,99999989,pr,WinChip,munsafedma
phiopt,reflects,bottom,99999959,128N,careful,ambiguous
fpackstructn,realworld,msingleexit,99999931,0xffff,maxmimum,fdumprtldbr
simplified,mpopcntb,FrontCover,99999971,523x,requisite,crc
cede,fdumprtlbtl2,atmega649a,99999941,LC_MESSAGES,errno,Default
Paul--) 

이것이 병합 스크립트입니다. 데이터 생성 스크립트가 유용한 정보를 제공하면 게시할 수 있습니다.

Paul--) cat datMerge
#! /bin/bash
#: datMerge

LC_ALL="C"

function Merge {

    local AWK='''
BEGIN { FS = ","; OFS = ","; K = 170; Null = "Default"; }
NR == FNR { htMap[$1] = $2; next; }
{ printf ("%s%s%s\n", $0, OFS, ($(K) in htMap) ? htMap[$(K)] : Null); }
'''
    awk "${AWK}" "${@}"
}

    Merge "FileB.max.csv" "FileA.max.csv" > "FileC.max.csv"

Paul--) 

관련 정보