awk를 사용하여 다른 파일의 여러 열을 연결합니다.

awk를 사용하여 다른 파일의 여러 열을 연결합니다.

다음과 같이 4개의 tsv(탭으로 구분) 파일이 있습니다.

파일 1:

abc 1
def 2
ghi 3

파일_2:

abc 2
ghi 3

파일_3:

def 1
ghi 2
jkl 4

파일_4:

ghi 3
jkl 4

이 파일을 결합하여 다음과 같은 1개의 tsv 파일을 얻고 싶습니다.

dataset file_1 file_2 file_3 file_4
abc     1      2             
def     2      4            
ghi     3      3      2      3
jkl                   4      4

나는 사용해 보았습니다.awk

$ awk '
    BEGIN{OFS=FS="\t"} 
    FNR==1{f = f "\t" FILENAME} 
    NR==FNR{a[$1] = $2} 
    NR!=FNR{a[$1] = a[$1] "\t" $2} 
    END{printf "dataset%s\n", f; for(i in a) print i, a[i]}
  ' file_{1..4}

이 명령은 작동하지만 값이 전송됩니다. 첫 번째와 두 번째 열의 값이 null이고 세 번째와 네 번째 열의 값이 4와 4인 경우 이 명령에서 얻는 출력은 첫 번째와 두 번째 열의 값은 4이지만 세 번째 열과 네 번째 열은 값이 있다는 것입니다. null 값이 있습니다. 그래서 제가 awk언급한 내용을 사용하여 TSV 파일을 개별적으로 결합 하려고 했습니다 . 먼저 for file_1file_2get 을 수행 output_1한 다음 Join file_3file_4get 을 수행합니다 output_2. 그 후에는 출력_1과 출력_2 병합을 사용 $ join output_1 output_2하지만 4개 파일에 있는 값만 가져옵니다. 하나의 파일에만 존재하던 데이터를 잃어버렸습니다.

조언해주시면 정말 감사하겠습니다.

감사해요

답변1

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ datasets[$1]; fnames[FILENAME]; vals[$1,FILENAME] = $2 }
END {
    printf "%s", "dataset"
    for (fname in fnames) {
        printf "%s%s", OFS, fname
    }
    print ""
    for (dataset in datasets) {
        printf "%s", dataset
        for (fname in fnames) {
            printf "%s%s", OFS, vals[dataset,fname]
        }
        print ""
    }
}

$ tail -n +1 file?
==> file1 <==
a       1
b       2
c       3

==> file2 <==
a       2
c       3

$ awk -f tst.awk file1 file2
dataset file1   file2
a       1       2
b       2
c       3       3

목록에 필요한 만큼 파일을 추가합니다.

답변2

join (GNU coreutils) 8.30"프로세스 교체"를 통해 시도해 볼 수 있습니다.

join -a1 -a2 -t"    " -oauto  -e " " <(join -a1 -a2 -t" " -oauto  -e "" file[12]) <(join -a1 -a2 -t"    " -oauto  -e " " file[34])
abc 1   2        
def 2       1    
ghi 3   3   2   3
jkl         4   4

이러한 -t옵션에는 <TAB>문자 값이 있습니다.

답변3

지금은 조언을 드립니다. 필요한 경우 나중에 코드를 작성할 수 있습니다.

모든 파일을 읽을 때 세 개의 배열을 유지합니다.

(a) 각각의 새 파일에 대해 파일 이름의 해시 목록.
(b) 각각의 새로운 데이터 세트에 대해 해시 목록은 $1입니다.
(c) 각 행에는 값의 해시 목록이 있습니다.

FNR == 1 { ++htFile[FILENAME]; }
! ($1 in htSet) { ++htSet[$1]; }
{ htVal [FILENAME, $1] = $2; }

End 함수에서 htFile 및 htSet을 반복합니다.

function Table (r, c, buf) {
    buf = "dataset";
    for (c in htFile)
        buf = sprint ("%s\t%s", buf, htFile[c]);
    print buf;
    for (r in htSet) {
        buf = "";
        for (c in htFile)
            buf = sprint ("%s\t%s", buf, htVal[c, r]);
        print substr (buf, 2);
    }
}
END { Table( ); }

이는 출력 테이블의 파일 및 데이터세트 순서를 유지하지 않습니다. 이것이 중요한 경우 테이블의 정렬된 버전을 유지하고 원래 순서로 반복할 수 있습니다.

관련 정보