我有以下要求。我有一个输入流,需要将其截断为某个固定长度的字节。我事先不知道输入流的长度。如果流的长度小于设置的长度,我想用零字节填充它。我尝试使用truncate
,但显然它只能处理文件,不能处理标准输入。
例如,假设我们的输入流 (stdin) 是TEST
,并且我们希望达到 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
对于zsh
,使用其r
ight 填充(和截断)参数扩展标志(以及p
用于转义序列的标志,例如\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
要高效得多)。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
实现我的目标更适合。