나는 거대한 파일(수 기가바이트 등)을 가지고 있고 다양한 도구(분할 등)를 시도했지만 내 필요에 따라 이 작업을 awk에서 수행해야 합니다.
기본적으로 awk의 기능을 에뮬레이트하고 싶습니다 split -b 1 file
(제공된 매뉴얼 페이지와 명령으로 판단하면 파일을 바이트당 1바이트로 분할함).
또한 생성된 파일의 파일 이름(증분)이 스크립트가 실행되는 동안 stdout에 인쇄되어 주로 다른 스크립트 등에서 변수로 사용할 수 있기를 원합니다.
편집: 지금까지 내가 한 일은 다음과 같습니다.
awk '{for(i=1;i<=length;i++) print substr($0, i, 1)}' filename
파일 이름 세부정보
다른 파일을 덮어쓰지 않으려면 파일 이름을 늘려야 합니다. (숫자 또는 영숫자).
비교를 위해 split
coreutils의 도구는 다음과 같이 문자를 사용하여 파일 이름을 생성합니다.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
비표준 확장입니다. RT
AFAIK GNU에만 해당됩니다.
답변2
1바이트 파일을 생성할 때 수행되는 작업은 split
파일에 순차적으로 번호를 매기는 것뿐이지만 최대 256개의 서로 다른 파일만 생성할 수 있습니다. 더 이상 가능한 파일 내용이 없으며 256개만 있습니다.
또한, 여러 GB 파일을 동일한 개수의 1바이트 파일로 변환하면 처리할 데이터 크기가 크게 늘어나므로(ext4 파일 시스템의 경우 4000개 이상) 각 파일에 대한 액세스 속도도 느려집니다.
그러나 말씀하신 대로 데이터에 대한 추가 처리를 수행하는 또 다른 옵션이 있습니다.
또한 생성된 파일의 파일 이름(증분)이 스크립트가 실행되는 동안 stdout에 인쇄되어 주로 다른 스크립트 등에서 변수로 사용할 수 있기를 원합니다.
따라서 더 빠른 솔루션은 리소스(디스크 공간, 처리 능력, 시간 및 에너지) 소비를 크게 줄일 수 있습니다.
0x00
에서 까지 각각 1바이트로 구성된 256개의 파일을 생성합니다0xff
. 여기에는 가능한 모든 입력이 포함됩니다.a number
stdout+에서 생성됩니다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.
즉, 더 빠른 솔루션입니다.