Bash:在 CLI 上截断或裁剪二进制文件或 stdin 的一部分?

Bash:在 CLI 上截断或裁剪二进制文件或 stdin 的一部分?

如果我有一个二进制文件,或者一些带有原始二进制输出的命令,并且我正在寻找一个 shell(bash)命令来裁剪数据的特定部分,即给定的开始和长度或结束偏移量(以字节为单位)。

例如,假设file.bin包含abcdefghijk,我会做类似的事情:

cat file.bin | crop 5 3

为了表明我只想保留偏移量为 5 且长度为 3 的部分,因此此示例将输出fgh

我知道有这个cut命令,但它适用于文本内容并逐行处理输入。就我而言,我通常处理二进制数据,因此没有行的概念。我只是想以字节为单位指定要裁剪的部分。

有没有二进制替代品cut

答案1

POSIXtailwith-c可以处理任意数据。不幸的是POSIXhead不能。当仅限于 POSIX 时,您需要dd;或者像这样:

<file.bin tail -c +6 | dd bs=1 count=3 2>/dev/null

或者像这样:

<file.bin dd bs=1 skip=5 count=3 2>/dev/null

bs=1可能不是最优的,但即使你的skip=count=可以重新计算为更大的bs=dd仅使用 POSIX才bs=1适合您

GNUdd支持iflag=fullblock可能会在更大的情况下有所帮助bs=。对于您使用 GNU 的情况,dd更好的选择是iflag=skip_bytes,count_bytes

<file.bin dd iflag=skip_bytes,count_bytes skip=5 count=3 2>/dev/null

上述命令使用默认值bs=512,尽管 5 和 3 都不是 512 的倍数,它仍能正常工作。此命令应该可以与任何合理的 一起使用bs=

如果如果您head支持-c计数字节,则在这种模式下读取时很可能不会等待整行。这导致了以下方法:

<file.bin tail -c +6 | head -c 3

可能还有其他解决方案。注意,如果command1打印输入的前 5 个字节,然后command2打印输入的前 3 个字节,那么

{ command1 >/dev/null; command2; } <file.bin

可能或者可能不会工作。一般来说 command1可能会读更多的超过 5 个字节(并且仍然将 5 打印到其标准输出),因此当command2开始读取时,指针可能位于错误的位置。我给您的命令不遵循这种可能有缺陷的模式。

答案2

dd就可以了。如果您需要一个字节的粒度,则必须将块大小设置为 1:

cat file.bin | dd bs=1 skip=5 count=3

相关内容