(AWK) Csv 열의 동일한 변수를 다른 파일로 분리

(AWK) Csv 열의 동일한 변수를 다른 파일로 분리

두 개의 열이 있는 test1.csv 파일이 있습니다.

group,email
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]

내 목표는 첫 번째 열의 값을 기반으로 별도의 텍스트 파일을 만드는 것입니다.

예를 들어:

첫 번째 파일 이름은[이메일 보호됨]그리고 포함

[email protected]
[email protected]
[email protected]
[email protected]

첫 번째 파일 이름은[이메일 보호됨]그리고 포함

[email protected]
[email protected]

등.

이 awk 명령이 있습니다

awk -F"," 'NR==1{header=$0}NR>2&&!a[$1]++{print header > (""$1"")}NR>2{print > (""$1"")}' test1.csv

그러나 파일 이름이 올바르게 지정되었음에도 불구하고 결과는 내가 정말로 원하는 것이 아닙니다.

group,email
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]

또한 .csv 파일이 너무 커질 때마다 "Awk: 열린 파일이 너무 많습니다"라는 메시지가 표시됩니다.

도움을 주시면 감사하겠습니다. 또한 sed나 grep과 같은 다른 언어도 살펴보세요.

답변1

이것이 당신에게 필요한 것입니다:

awk -F ',' 'NR<2{next} p1!=$1&&p1{close(p1)} {p1=$1;print $2>p1}' file
  • NR<2{next}: 제목을 건너뜁니다.
  • p1!=$1&&p1{close(p1)}: p1이전 줄의 첫 번째 필드( )가 현재 줄의 첫 번째 필드와 다른 경우 "너무 많은 열린 파일"이 발생하지 않도록 이전 출력 파일이 닫힙니다(아직 열린 파일이 없는 한). 및 열기 p1). 설정되지 않음).
  • {p1=$1;print $2>p1}: 첫 번째 필드를 p1변수에 넣고 두 번째 필드를 첫 번째 필드 이름의 파일에 인쇄합니다.

file위의 awk에서는 제공된 예에 표시된 것처럼 첫 번째 필드가 동일한 행이 에서 함께 그룹화되어 있다고 가정합니다 . 그렇지 않은 경우 간단한 해결책은 awk에 정렬된 입력을 제공하고 헤더를 명시적으로 건너뛰는 것입니다(헤더가 더 이상 첫 번째 줄에 없기 때문에).

sort file | awk -F ',' '/^group,email$/{next} p1!=$1&&p1{close(p1)} {p1=$1;print $2>p1}'

답변2

awk제공된 파일 이름으로 직접 리디렉션 할 수 있습니다 (도메인 이름은 공백에 안전해야 함).$2$1

awk -F, 'NR>1{print $2 > $1}' file

헤더를 건너뛰고 파일을 열어 둡니다. 헤더를 ++h[$1]==1쓸 새 파일 인지 테스트한 다음 다음을 사용하여 추가하여 이 문제를 해결할 수 있습니다.>>>$2close($1)

awk -F, '
  NR==1{header=$0}
  NR>1{
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; close ($1)
}' file

중복을 피하려면 ++f[$0]==1첨부하기 전에 테스트하십시오.

awk -F, '
  NR==1{header=$0}
  NR>1&&++f[$0]==1{
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; close ($1)
}' file
head *.com

==> [email protected] <==
group,email
[email protected]
[email protected]
[email protected]
[email protected]

==> [email protected] <==
group,email
[email protected]
[email protected]

==> [email protected] <==
group,email
[email protected]
[email protected]
[email protected]

파일이 완전히 또는 부분적으로 정렬된 경우 다음과 같이 각 줄을 맹목적으로 열고 닫는 것을 방지할 수 있습니다.

awk -F, '
  NR==1{header=$0}
  NR>1&&++f[$0]==1{
    if ($1 != old) close(old);
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; old=$1
}' file

이는 데이터 파일을 사용하기 때문에 $2 >> 두 번째 블록이 있어도 상관 없으며 $1 새 블록에 의해 삭제되지 않습니다.>

답변3

밀러 사용(https://github.com/johnkerl/miller) 간단히 말해서

mlr --csv put -q 'tee > $group, $*' ./input.csv
mlr -I --c2n cut -f email ./group*@*

이건 이상한 일이 아니지만 당신에게 효과가 있을 거라고 생각했어요

답변4

$ awk '{print (NR>1),$0}' file | sort -k1,1n -k2 | cut -d' ' -f2- |
    awk -F, '
        NR==1 { hdr=$0; next }
        $1 != out { close(out); out=$1; print hdr > out }
        { print $2 " > " out }
    '

위의 코드는 거의 모든 크기의 입력 파일에 대한 모든 awk에서 작동하며 입력 줄의 순서는 상관 없으며 빠릅니다.

테스트 완료 후 실제로 출력 파일을 생성 print $2 " > " out하도록 변경되었습니다 .print $2 > out

관련 정보