巨大なファイル(数ギガバイトなど)があり、さまざまなツール(スプリットなど)を試しましたが、自分のニーズのためにawkでこれを行う必要があります。
基本的に、私は何をエミュレートしたいsplit -b 1 file
はawkで行います(提供されているマニュアルページとコマンドから、ファイルはそれぞれ1バイトずつ分割されます)。
また、スクリプトの実行中に、生成されたファイルのファイル名(インクリメント)がstdoutに出力されるようにしたいので、他のスクリプトで変数などとして使用できます。
編集:ここで私がこれまでに行ったこと
awk '{for(i=1;i<=length;i++) print substr($0, i, 1)}' filename
ファイル名の詳細
他のファイルを上書きしないように、ファイル名を増やす必要があります。 (数値または英数字)。
比較するために、coreutilsのsplit
ツールは、次のように文字を使用してファイル名を生成します:xa xb...xaa
私はそれを持っているか、可能であれば数値のみを使いたい:1 2..444
または/および英数字のファイル名:a1 a2
GNU awk
を使用すると、次のことができます。
LC_ALL=C gawk -v RS='.{1}' '
{
file = "filename" ++n
print file
printf "%s", RT > file
close(file)
}' < input
しかし、ほとんどのファイルシステムでは、バイトごとに1つのファイルを作成するため、ディスクスペース(ほとんどのファイルシステムでは1バイトのファイルが数キロバイトのディスクスペースを占有しているため)またはiノードがすぐに不足するか、パフォーマンスが恐ろしくなります。数十万バイトの入力後(ディレクトリにエントリを追加するコストは、いくつかのファイルシステムの実装があるディレクトリのサイズとともに増加するため)
LC_ALL=C
は、.
が文字ではなくバイトで一致するためのものですRS='.{1}'
は、レコード区切り文字を1
単一文字(LC_ALL=C
を含む1バイト)に設定します。 RS=.
は、レコードセパレータがドット文字であることを意味するため機能しません。 RS
を正規表現と見なすには、gawk
を複数の文字にする必要があります。 (.)
と.|.
も機能しますが、私のテストでは、.{1}
が3の中で最も効率的であることがわかりました。RT
には、RS
に一致したテキストが含まれます。正規表現としてのRS
、バイナリデータを処理する機能、およびRT
はすべて非標準の拡張機能です。 RT
はGNU固有のAFAIKです。
split
が行うこと(1バイトのファイルを生成する場合)は、ファイルに順番に番号を付けることですが、最大256個の異なるファイルのみを生成します。ファイルの内容はありません。256だけです。
また、マルチギガバイトのファイルをそれぞれ1バイトの同量のファイルに変換すると、処理するデータのサイズが大きくなり(ext4ファイルシステムでは4000を超える)、各ファイルへのアクセスが遅くなります。
ただし、データに対して追加の処理を実行するとも言われている代替手段があります。
また、スクリプトの実行中に、生成されたファイルのファイル名(インクリメント)をstdoutに出力させたいので、他のスクリプトで変数などとして使用できます。
したがって、リソースの消費量(ディスク容量、処理能力、時間、エネルギー)を大幅に削減するはるかに高速なソリューションは次のとおりです。
0x00
から0xff
までの1バイトの256ファイルを生成します。これは可能な入力をカバーします。a number
+ a file name
で生成します。番号は、最初からの入力ファイル内の位置です。ファイル名は、入力内のバイトの値を示すために上記で作成した256ファイルの1つです。事前に256ファイルを生成できます(bash)。
for((i=0;i<=255;i++)); do
file=prefix$(printf '%03d' "$i");
printf '%b' "$(printf '\\x%x' "$i")" >$file;
done
または、数ギガバイトのファイルの処理中に必要なものを生成します。
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.
つまり、より高速なソリューションです。