Awk - 생성된 파일 이름을 표준 출력으로 지정하면서 각 바이트를 자체 파일로 분할합니다.

Awk - 생성된 파일 이름을 표준 출력으로 지정하면서 각 바이트를 자체 파일로 분할합니다.

나는 거대한 파일(수 기가바이트 등)을 가지고 있고 다양한 도구(분할 등)를 시도했지만 내 필요에 따라 이 작업을 awk에서 수행해야 합니다.

기본적으로 awk의 기능을 에뮬레이트하고 싶습니다 split -b 1 file(제공된 매뉴얼 페이지와 명령으로 판단하면 파일을 바이트당 1바이트로 분할함).

또한 생성된 파일의 파일 이름(증분)이 스크립트가 실행되는 동안 stdout에 인쇄되어 주로 다른 스크립트 등에서 변수로 사용할 수 있기를 원합니다.

편집: 지금까지 내가 한 일은 다음과 같습니다.

awk '{for(i=1;i<=length;i++) print substr($0, i, 1)}' filename

파일 이름 세부정보

다른 파일을 덮어쓰지 않으려면 파일 이름을 늘려야 합니다. (숫자 또는 영숫자).

비교를 위해 splitcoreutils의 도구는 다음과 같이 문자를 사용하여 파일 이름을 생성합니다.xa xb...xaa

나는 다음 중 하나를 원합니다. 또는 가능하다면 숫자만 원합니다: 1 2..444 또는/및 영숫자 파일 이름:a1 a2

답변1

GNU를 사용하면 awk다음과 같은 작업을 수행할 수 있습니다.

LC_ALL=C gawk -v RS='.{1}' '
  {
    file = "filename" ++n
    print file
    printf "%s", RT > file
    close(file)
  }' < input

그러나 대부분의 파일 시스템에서 바이트당 하나의 파일을 생성한다는 점을 고려하면 디스크 공간(대부분의 파일 시스템에서 1바이트 파일이 여전히 몇 KB의 디스크 공간을 차지하므로)이나 inode가 빨리 부족해질 수 있습니다. 그렇지 않으면 성능이 매우 나빠질 수 있습니다. 수십만 바이트의 입력(여러 파일 시스템 구현이 있는 디렉토리 크기에 따라 디렉토리에 항목을 추가하는 비용이 증가하기 때문)

  • LC_ALL=C.문자 대신 바이트를 일치시키는 데 사용됩니다 .
  • RS='.{1}'레코드 구분 기호를 1단일 문자(로 된 단일 바이트 LC_ALL=C)로 설정합니다. RS=.레코드 구분 기호가 점 문자라는 의미이므로 작동하지 않습니다. 정규식으로 간주하려면 RS여러 문자가 필요합니다 . 또한 작동하지만 테스트 결과 3가지 중에서 이것이 가장 효과적인 것으로 나타났습니다.gawk(.).|..{1}
  • RT일치하는 텍스트가 포함되어 있습니다 RS.

RS정규식으로서 이진 데이터를 처리할 수 있으며 RT비표준 확장입니다. RTAFAIK GNU에만 해당됩니다.

답변2

1바이트 파일을 생성할 때 수행되는 작업은 split파일에 순차적으로 번호를 매기는 것뿐이지만 최대 256개의 서로 다른 파일만 생성할 수 있습니다. 더 이상 가능한 파일 내용이 없으며 256개만 있습니다.

또한, 여러 GB 파일을 동일한 개수의 1바이트 파일로 변환하면 처리할 데이터 크기가 크게 늘어나므로(ext4 파일 시스템의 경우 4000개 이상) 각 파일에 대한 액세스 속도도 느려집니다.

그러나 말씀하신 대로 데이터에 대한 추가 처리를 수행하는 또 다른 옵션이 있습니다.

또한 생성된 파일의 파일 이름(증분)이 스크립트가 실행되는 동안 stdout에 인쇄되어 주로 다른 스크립트 등에서 변수로 사용할 수 있기를 원합니다.

따라서 더 빠른 솔루션은 리소스(디스크 공간, 처리 능력, 시간 및 에너지) 소비를 크게 줄일 수 있습니다.

  • 0x00에서 까지 각각 1바이트로 구성된 256개의 파일을 생성합니다 0xff. 여기에는 가능한 모든 입력이 포함됩니다.
  • a numberstdout+에서 생성됩니다 a file name. 이 숫자는 입력 파일의 시작 위치입니다. 파일 이름은 위에서 생성된 256개 파일 중 하나이며 입력 내의 바이트 값을 제공합니다.

256개의 파일을 사전 생성할 수 있습니다(bash):

for((i=0;i<=255;i++)); do 
    file=prefix$(printf '%03d' "$i"); 
    printf '%b' "$(printf '\\x%x' "$i")" >$file;
done

또는 여러 GB 파일로 작업할 때 필요한 파일을 생성하세요.

LC_ALL=C gawk '
  BEGIN{                                # 
      RS=".{1}"                         # set the record separator
      for(i=0;i<256;i++){
          ord[ sprintf("%c",i) ] = i    # help array ord
      }
  }
  {
    position = ++n                      # keep count of bytes read
    file = "prefix" ord[RT]             # find the file name to use
    if ( ! seen[file] ) {               # Have we seen this file ?
        printf "%s", RT > file          # If not, create it.
        close(file)                     # close the file
        seen[file]=1                    # record that we have seen it.
    }
    print position, file                # print information for next script
  }
' ./input                               # file to process.

즉, 더 빠른 솔루션입니다.

관련 정보