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つのファイルを作成することを考慮すると、ディスク容量(ほとんどのファイルシステムでは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からの各バイトで構成される256個のファイルを作成します0xff。これにはすべての可能な入力が含まれます。
  • a numberstdout+で作成されます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

または、複数の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.

つまり、より速い解決策です。

関連情報