모든 헤더/열을 공유하지 않는 CSV 파일 결합/병합

모든 헤더/열을 공유하지 않는 CSV 파일 결합/병합

데이터 로깅 시스템의 1000개 파일이 포함된 디렉토리가 있는데, 각 파일은 최대 40,000줄 이상을 포함할 수 있습니다. 문제는 때때로 하나 이상의 센서에서 데이터가 기록되지 않아 손실된다는 것입니다.

파일 1:

A,B,C,D,F

10,20,10,20,5

파일 2:

B,C,D,E,F

20,10,20,5,10

파일 3:

D,E,F


10,30,20

원하는 결과는 모든 파일을 하나의 헤더로 병합/연결하는 것입니다. 입력 파일에 열이 누락된 경우(손상된 센서로 인해) 해당 섹션은 null 값으로 대체됩니다.

A,B,C,D,E,F

10,20,10,20,,5

,20,10,20,5,10

,,,10,30,20

마지막 열 F는 날짜/시간 스탬프이므로 항상 존재합니다.

이 답변을 찾았지만 모든 헤더/열이 모든 파일에서 동일하다고 가정합니다.

헤더 순서가 다른 여러 개의 큰 CSV 파일 붙여넣기

나도 이 문제를 발견했다여러 CSV 파일을 병합하여 일치하는 열과 일치하지 않는 열을 얻습니다.하지만 제가 사용할 수 있을 만큼 답변이 완전하지 않습니다.

감사해요

답변1

매우 깨끗하고 간단한 대안 도구를 사용해보고 싶다면(https://github.com/johnkerl/miller), 입력 CSV 파일이 포함된 폴더부터 시작하여 이 명령을 사용합니다.

mlr --csv unsparsify *.csv >out.csv

당신은 할 것

A,B,C,D,F,E
10,20,10,20,5,
,20,10,20,10,5
,,,10,20,30

F a 를 종료하려면 다음 명령을 사용하세요.

mlr --csv unsparsify then reorder -e -f F *.csv

파일이 많은 경우 다음 두 단계로 수행할 수 있습니다.

mlr --icsv cat *.csv >tmp.txt
mlr --ocsv unsparsify tmp.txt >out.csv

답변2

BEGIN {
        OFS = FS = ","

        # Parse given column headers and remeber their order.

        # nf will be the number of fields we'd want in the output.
        nf = split(pick, header)
        for (i = 1; i <= nf; ++i)
                order[header[i]] = i

        # Output headers.
        print pick
}

FNR == 1 {
        # Parse column headers from input file.

        delete reorder

        for (i = 1; i <= NF; ++i)
                # If the current header is one that we'd like to pick...
                if ($i in order)
                        # ... record what column it is located in.
                        reorder[order[$i]] = i

        next
}

{
        # Process data fields from input file.

        # We build a new output record, so explicitly split the current record
        # and save it in the field array, then empty the record and rebuild.
        split($0, field)
        $0 = ""

        for (i = 1; i <= nf; ++i)
                # If reorder[i] is zero, it's a column that is not available in the
                # current file.
                $i = (reorder[i] == 0 ? "" : field[reorder[i]])

        print
}

awk스크립트는 추출하려는 열을 특정 순서로 매개변수로 선택하고 각 입력 파일에서 해당 열을 추출합니다.

질문에 표시되는 데이터의 예:

$ awk -v pick='A,B,C,D,E,F' -f script.awk file*.csv
A,B,C,D,E,F
10,20,10,20,,5
,20,10,20,5,10
,,,10,30,20
$ awk -v pick='F,B,A' -f script.awk file*.csv
F,B,A
5,20,10
10,20,
20,,

답변3

데이터 행 사이에 실제 빈 줄이 없다고 가정하고 GNU awk를 사용하여 정렬합니다.

$ cat tst.awk
BEGIN { FS=OFS="," }
FNR==1 {
    delete f
    for (i=1; i<=NF; i++) {
        f[$i] = i
        flds[$i]
    }
    numFiles++
    next
}
{
    for (tag in f) {
        val[numFiles,tag] = $(f[tag])
    }
}
END {
    PROCINFO["sorted_in"] = "@val_str_asc"
    sep = ""
    for (tag in flds) {
        printf "%s%s", sep, tag
        sep = OFS
    }
    print ""
    for (fileNr=1; fileNr<=numFiles; fileNr++) {
        sep = ""
        for (tag in flds) {
            printf "%s%s", sep, val[fileNr,tag]
            sep = OFS
        }
        print ""
    }
}

.

$ awk -f tst.awk file{1..3}
A,B,C,D,E,F
10,20,10,20,,5
,20,10,20,5,10
,,,10,30,20

관련 정보