NULLを使用して標準入力を希望の長さで埋める最良の方法

NULLを使用して標準入力を希望の長さで埋める最良の方法

次の要件があります。固定長のバイトに切り捨てる必要がある入力ストリームがあります。入力ストリームの長さを事前に知りません。ストリームの長さが設定された長さより小さい場合は、0バイトで埋めたいと思います。を使ってみましたが、truncate標準入力ではないファイルだけを処理できるようです。

TESTたとえば、入力ストリーム(stdin)があり、長さが10バイトになりたいとします。その後、出力ストリーム(stdout)はTEST\x00\x00\x00\x00\x00

これを明確にするために、例は小さな文字列を使用して行われましたが、結果は大規模ストリーム(メガバイトからギガバイトまで)でもうまくいくはずです。そして現在私が使用しているコンテナはUbuntuベースです。

答え1

GNUの使用dd:

$ printf %s test | dd iflag=fullblock bs=10 status=none conv=sync count=1 | hexdump -C
00000000  74 65 73 74 00 00 00 00  00 00                    |test......|
0000000a

の場合、ightパディング(および切り捨て)引数拡張フラグ(パディング文字列の拡張などのエスケープシーケンスのフラグ)をzsh使用します。rp\0

$ string=test
$ printf %s ${(pr[10][\0])string} | hexdump -C
00000000  74 65 73 74 00 00 00 00  00 00                    |test......|
0000000a

しかし、10までパディングされることに注意してください。数値、10バイトではありません。multibyteこのオプションをオフにすると、これを変更できますset +o multibyte

$ string=tést
$ printf %s ${(pr[10][\0])string} | hexdump -C
00000000  74 c3 a9 73 74 00 00 00  00 00 00                 |t..st......|
0000000b
$ printf %s ${(pr[10][\0])string} | wc -mc
     10      11
$ set +o multibyte
$ printf %s ${(bpr[10][\0])string} | hexdump -C
00000000  74 c3 a9 73 74 00 00 00  00 00                    |t..st.....|
0000000a
$ printf %s ${(bpr[10][\0])string} | wc -mc
      9      10

これらのソリューションは、システムのRAM容量よりも大きいサイズでは拡張できません。

@ilkkachuがコメントで提案したように、大きなサイズの場合

{ printf %s test; cat /dev/zero; } | head -c 1000000000

より効率的です(標準ではありませんが、一般的で、head -c一度に1バイトを読み書きするよりもはるかに効率的です)。dd bs=1

ファイルに出力する場合は、リソース制限を使用して以下を切り捨てることもできます。

(
  ulimit -f 1048576 # KiB
  printf %s test
  cat /dev/zero
) > file

答え2

次の解決策が見つかりました。

echo -n 'TEST' | cat - /dev/zero | dd bs=1 count=10 2>/dev/null | hexdump

これは動作し、次を正しく出力します。

0000000 4554 5453 0000 0000 0000
000000a

したがって、これは少なくともLinux上で動作し、プラットフォーム間の移植性は気にしません。しかし、dd私の目標を達成するためのより適切なコマンドがあるかもしれないと思います。

関連情報