구분된 여러 파일의 데이터를 변수 열이 포함된 하나의 파일로 쌓습니다.

구분된 여러 파일의 데이터를 변수 열이 포함된 하나의 파일로 쌓습니다.

저는 스크립팅이 처음입니다. Unix에서 파일 병합 문제가 발생했습니다. 방향을 찾고 있었는데 우연히 이 사이트를 발견했습니다. 훌륭한 게시물과 답변을 많이 보았지만 내 문제에 대한 해결책을 찾을 수 없습니다. 어떤 도움이라도 대단히 감사하겠습니다 ..

세 개의 csv 파일(> Apex_10_Latest.csv, Apex_20_Latest.csv, Apex_30_Latest.csv)이 있습니다. 이 3개 파일의 열 수는 다양합니다. 일반적으로 번호에 따라 최신 파일의 끝에 새로운 열이 추가될 수 있습니다. 그래서 최신 헤더를 가져와 3개 파일 모두의 데이터를 새 파일 Apex.csv에 스택하고 싶습니다. 최신 파일보다 열 수가 적을 수 있는 이전 파일의 데이터를 스택할 때 적절한 구분 기호를 사용하여 데이터를 Null로 채우고 싶습니다.

또한 이 작업은 동일한 폴더에 있는 여러 파일 세트(각각 3개 파일)에 대해 반복적으로 수행되어야 합니다. - Apex_10_Latest.csv, Apex_20_Latest.csv, Apex_30_Latest.csv - Apex.csv로 병합 - Code_10_Latest.csv, Code_20_Latest.csv, Code_30_Latest.csv - Code.csv로 병합 - Trans_10_Latest.csv, Trans_20_Latest.cs v. Trans_30_Latest.csv - ImportTrans.csv 병합

소스 파일의 형식과 대상 파일의 형식은 다음과 같습니다... 소스 파일:

  • Apex_30_Latest.csv:
    ABCD
    1,2,3,4
    2,3,4,5
    3,4,5,6

  • Apex_20_Latest.csv:
    에이,비,씨
    4,5,6
    5,6,7
    6,7,8

  • Apex_10_Latest.csv:
    에이, 비
    7,8
    8,9
    9,10

의도한 대상 파일:

  • Apex.csv
    ABCD
    1,2,3,4
    2,3,4,5
    3,4,5,6
    4,5,6,,
    5,6,7,,
    6,7,8,,
    7,8,,,
    8, 9,,,
    9,10,,,

감사해요...

답변1


밀러(http://johnkerl.org/miller/doc/) 평소처럼 쉽습니다

mlr --csv unsparsify Apex_*_Latest.csv

당신을 위한

A,B,C,D
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,
5,6,7,
6,7,8,
7,8,,
8,9,,
9,10,,

답변2

  cat $(ls -1 Apex_*_Latest.csv | sort -nr -k2 -t'_') | awk -F"," '{
           if (NR==1){
                nfm=NF};
           for (i=1;i<=nfm;i++) {
                printf $i","};
           print ""}' >Apex.csv

열 수가 가장 많은 행이 먼저 나오도록 sort두 번째 필드(30,20,10..)와 파일을 기준으로 파일 이름을 반대로 바꿀 수 있습니다 .cat

awk그런 다음 첫 번째 행에서 가장 많은 수의 열을 얻을 수 있습니다NFNR if (NR==1){nfm=NF}

그런 다음 (열 번호) 가 필드 번호에 인쇄된 값 보다 크거나 같고 그 뒤에 ","가 올 for때까지 루프를 실행합니다 . 필드에 값이 없는 경우 에만 인쇄됩니다 (최신 파일보다 열 수가 적은 경우 발생) .infmii,

답변3

이전 답변이 가장 좋다고 생각합니다. Perl과 Python이 커진 이후로 수년 동안 awk를 사용하지 않았기 때문에 다른 접근 방식을 보여주고 있습니다. 나는 awk가 괜찮다고 생각합니다. 단지 쉘, sed, Python 및/또는 Perl의 혼합이 내 작업에 더 적합하다는 것입니다.

하지만 이 경우에는 누구나 awk 솔루션이 더 깔끔하고 읽기 쉽다는 것을 알 수 있다고 생각합니다. 생각해보면 awk를 명령줄 스프레드시트라거나 그와 유사한 것을 들어본 것 같습니다. :-)

원래 게시물에 따라 나는 파일 이름 형식에 의존하는 대신 ls 명령을 사용하여 파일 이름을 파일 수정 시간별로 정렬하도록 선택했습니다. 하나는 6이고 다른 하나는 6입니다.

따라서 비교를 위해 효율적이고 이식 가능하며 모듈식(?!)의 순수 셸 버전 솔루션이 있습니다.

    #!/bin/sh

    get_commas() {
        sed 's/[^,]//g; 1q' "$@"
    }

    get_extra_commas() {
        local maxcommas="$1"
        local file="$2"
        local new_commas=$(get_commas "$file")
        local extra_commas=""
        while [ "${new_commas}${extra_commas}" != "${maxcommas}" ]
        do
            extra_commas=",$extra_commas"
        done
        echo "$extra_commas"
    }

    unset header
    ls -t Apex*.csv |
    while read filename
    do
        if [ -z "$header" ]
        then
            header="$(sed 1q "$filename")"
            commas=$(echo "$header" | get_commas)
            echo "$header"
        fi
        extra_commas=$(get_extra_commas $commas "$filename")
        sed "1d; s/\$/$extra_commas/" "$filename"
    done

답변4

이것이 구현된 답변입니다.밀러:

$ cat rect.mlr
for (k,v in $*) {
  @fields[k] = v; # retain already-seen field names
}
for (k,v in @fields) {
  if (isabsent($[k])) {
    $[k] = "";
  }
}

$ mlr --csvlite put -f rect.mlr Apex_30_Latest.csv Apex_20_Latest.csv Apex_10_Latest.csv
A,B,C,D
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,
5,6,7,
6,7,8,
7,8,,
8,9,,
9,10,,

Miller는 기본적으로 명명된 열을 처리하므로 헤더 행 관리가 더 간단해집니다.

관련 정보