두 파일의 열을 결합하여 별도의 출력 파일로 분리합니다.

두 파일의 열을 결합하여 별도의 출력 파일로 분리합니다.

다음과 같이 동일한 첫 번째 열과 첫 번째 행(헤더)을 공유하는 두 개의 큰 csv 파일이 있습니다. etc는 동일한 패턴을 가진 더 많은 값을 의미합니다.

파일 1.csv

names,text1,text2,text3,etc
A,1,4,3 ...
B,5,2,8 ...
C,3,7,4 ...
D,9,1,3 ...
etc

파일 2.csv

names,text1,test2,text3,etc
A,7,2,9 ...
B,3,0,6 ...
C,8,7,2 ...
D,1,5,6 ...
etc

file1.csv 및 file2.csv의 열(일치하는 헤더 또는 열 번호 포함)과 file1.csv의 첫 번째 열을 결합하여 헤더 중간을 기반으로 이름이 지정된 새 파일로 출력하는 코드/스크립트가 필요합니다.

따라서 다음과 같은 출력 파일 등이 제공됩니다.

텍스트1.csv

names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1
etc

텍스트2.csv

names,text2,text2
A,4,2
B,2,0
C,7,7
D,1,5
etc

텍스트3.csv

names,text3,text3
A,3,9
B,8,6
C,4,2
D,3,6
etc

답변1

예제에 따라 두 파일이 모두 정렬되어 있다고 가정하면(헤더 행 제외) 다음이 작동합니다.

column=2
until [[ $column > $(awk -F, '{ print NF; exit }' file1.csv) ]] ; do 
  join -t , -o 1.1,1.$column,2.$column file1.csv file2.csv > $(awk -F, '{ print $'$column'; exit }' file1.csv).csv 
  ((column++))
done

(조각을 빌렸습니다.@야노스존재하다이 답글.)

여기서 대부분의 마법은 join다음과 같이 수행됩니다. 출력 파일은 현재 디렉터리에 기록됩니다.

답변2

이는 다음과 유사합니다.미구엘 스비에라의 답변, 그러나 Bash를 사용하여 열 수를 계산하고 헤더를 가져옵니다.

IFS=, read -a headers < file1.csv
column=0
for h in "${headers[@]}"
do
        if [ "$((++column))" = 1 ]
        then
                continue
        fi
        join -t, -o "0,1.$column,2.$column" file1.csv file2.csv > "$h".csv
done

산출:

텍스트1.csv

names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1

텍스트2.csv

names,text2,test2
A,4,2
B,2,0
C,7,7
D,1,5

텍스트3.csv

names,text3,text3
A,3,9
B,8,6
C,4,2
D,3,6

노트:

  • read -a파일의 첫 번째 줄을 배열로 읽어옵니다.
  • column변수의 값은 1, 2, 3, 4, ...입니다. 1이면 출력 파일을 column생성하지 않기 때문에 처리되지 않습니다 .names.csv
  • 데이터 열의 경우 를 실행하면 join첫 번째 열(기본값)을 연결하여 해당 열과 column각 파일의 숫자 열을 출력합니다. 이부분은 거의 비슷해요미구엘 스비에라의 답변.
  • headers배열(즉, 첫 번째 줄의 필드 )을 사용하여 file1.csv출력 파일의 이름을 지정합니다.

그리고미구엘 스비에라의 답변그리고루딕의 답변, 이것은 가정합니다

  • 파일의 열 수가 동일합니다(이상적으로는 일치해야 함).
  • 파일의 라인(라인) 수가 동일합니다(또한 일치해야 함).

이는 파일이 정렬된 경우 가장 잘 작동합니다(그러나 정렬되지 않은 경우에도 작동할 수 있습니다.내부에동일한주문하다). 다시 말하지만, 이 작업은 Bash에서 수행되어야 합니다.

답변3

또한 시도

join -t, --header  file[12] | awk -F, -vOFS=, '
        {D = (NF-1)/2
         for (i=2; i<=D+1; i++) {if (FNR==1) FN[i] = $i
                                 print $1, $i, $(i+D)  >  FN[i] ".csv"
                                }
        }
'
cf te*

---------- text1.csv: ----------

names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1

---------- text2.csv: ----------

names,text2,test2
A,4,2
B,2,0
C,7,7
D,1,5

---------- text3.csv: ----------

names,text3,text3
A,3 ...,9 ...
B,8 ...,6 ...
C,4 ...,2 ...
D,3 ...,6 ...

이는 행과 필드 수가 동일한 입력 파일에 따라 다르므로 join해당 섹션이 올바르게 완료되고( --header옵션을 제공한다고 가정) awk반복 횟수를 계산할 수 있습니다. 그런 다음 필드를 반복하여 관련 파일에 인쇄합니다. 해당 파일의 이름은 첫 번째 줄에 캡처됩니다.

답변4

awk -F "," 'NR==FNR{a[FNR]=$2;b[$1]++;next}($1 in b){print $1,a[FNR],$2}' file1 file2

산출

file1
names text1 text1
A 1 7
B 5 3
C 3 8
D 9 1
awk -F "," 'NR==FNR{a[FNR]=$3;b[$1]++;next}($1 in b){print $1,a[FNR],$3}' file1 file2

산출

file2
names text2 test2
A 4 2
B 2 0
C 7 7
D 1 5
 awk -F "," 'NR==FNR{a[FNR]=$4;b[$1]++;next}($1 in b){print $1,a[FNR],$4}' file1 file2

산출

file3
names text3 text3
A 3  9
B 8 6
C 4 2
D 3 6

관련 정보