UNIX - 3개의 고유 값이 열의 모든 행에 해당하는 여러 파일로 파일을 분할하는 명령

UNIX - 3개의 고유 값이 열의 모든 행에 해당하는 여러 파일로 파일을 분할하는 명령

다음 입력 파일을 고려하십시오. 입력 파일:

C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6
0|1|2|3|7-5-2-6|5

필드 5(예: 첫 번째 레코드의 0-1-2-3)를 기준으로 출력 분할 파일은 다음과 같이 분할 파일 1이 될 것으로 예상됩니다.

C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5

분할 파일 2:

C1|C2|C3|C4|C5|C6
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6

분할 파일 3:

C1|C2|C3|C4|C5|C6
0|1|2|3|7-5-2-6|5

열 5를 기준으로 파일은 해당 열의 고유 값 3개마다 분할되어야 하며 열 5의 값을 반복하는 모든 행도 포함해야 합니다. 누군가 나를 도와줄 수 있나요?

답변1

작동합니다. 그것은 다음과 같습니다:

awk -F'|' -v fileformat="/abc/output/file_%04d.txt" -v max=3 -v field=5 '
  NR == 1 {header = $0; next}
  ! ($field in seen) {
    seen[$field]
    if (++n % max == 1) {
      close(out)
      out = sprintf(fileformat, ++f)
      print header > out
    }
  }
  {print > out}' < /abc/input/a.txt

답변2

해결책:

awk -F'|' 'NR==1{ h=$0; f=0; c=1 }NR>1{ 
              a[$5]; if(length(a)>3) { f=0;c++; delete a }; 
              fn="file"c".txt"; if(!f) print h > fn; print > fn; f++ 
           }' file
  • h=$0-머리글철사

  • f=0- 헤더 라인이 다음 새 파일에 인쇄되는 순간을 가리키는 플래그

  • c=1- 파일 이름 접미사(새 파일마다 증가)

  • a[$5]- a다섯 번째 필드에 대한 고유 값을 가진 인덱스 배열

  • if(length(a)>3) { f=0;c++; delete a }c++- 3개의 고유 값이 연속되면 다음 새 파일 이름( )을 시작합니다. (- delete a배열에서 모든 항목 제거 a)

  • fn="file"c".txt"- 현재 파일 이름


결과 보기:

for f in file[0-9]*.txt; do echo "$f"; cat "$f"; echo; done

산출:

file1.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5

file2.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6

file3.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|7-5-2-6|5

답변3

#!/bin/bash

awk -F '|' '
    function print_to_file(str) {
        print str > "file_"file_num;    
    }
    NR == 1 {header = $0;}
    NR > 1 {
        if(!buf) {
            file_num = 1;
            print_to_file(header);
        }
        if(buf != $5) {
            buf = $5;
            cnt++;
        }
        if(cnt > 3) {
            cnt = 1;
            file_num++;
            print_to_file(header);
        }
        print_to_file($0);
    }
' input.txt

산출:

$ tail -n +1 -- file_* # display content of all files with their filenames

==> file_1 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5

==> file_2 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6

==> file_3 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|7-5-2-6|5

관련 정보