我正在编写一些脚本,试图解析 Java 编写的一些数据
DataOutputStream#writeLong(...)
。由于 java 似乎总是写大端,所以我在向 od
提供字节时遇到问题。这是因为 od
始终假设字节序与您当前所在的 arch 的字节序相匹配,而我使用的是小型字节序机器。
我正在寻找一种简单的单行代码来反转字节顺序。假设您知道文件的最后 8 个字节是由上述
writeLong(...)
方法写入的长字节。我目前打印这么长的最佳尝试是
tail -c 8 file | tac | od -t d8
,但是
tac
似乎只适用于文本(很公平)。我找到了一些对 dd conv=swab
的引用,但这只能成对交换字节,而不能反转这八个字节。
有人知道这方面的好一句台词吗?
你可以使用 objcopy:
$ objcopy -I binary -O binary --reverse-bytes=num inputfile.bin outputfile.bin
其中 num 为 2 或 4。
用过dd,卢克!
dd if=sourcefile of=resultfile conv=swab
最终求助于Perl。使用了我在 PERL One Liners:
找到的单衬管tail -c 8 file | perl -0777e 'print scalar reverse <>' | od -t d8
0777
分隔符字符对我来说有点令人困惑,但是 debian admin 的 this 页面似乎表明它是“无记录分隔符”的占位符,触发每个字节的完整反向字节。
欢迎其他建议。
编辑:在 tac.c 的评论中找到另一个命令,我从 GNU coreutils 下载了它:
复制每个文件,或者复制标准输入(如果没有给出)或者当 遇到FILE名“-”,到标准输出用 记录顺序颠倒。记录由以下分隔符分隔 字符串的实例,如果没有给出则为换行符。默认情况下, 分隔符字符串附加到记录的末尾 文件中如下。
选项: -b, --before 分隔符附加到开头 文件中它前面的记录的名称。 -r, --regex 分隔符是正则表达式。 -s, --separator=分隔符 使用 SEPARATOR 作为记录分隔符。
要逐字节反转文件,请使用(在 bash、ksh 或 sh 中): tac -r -s '.\| ' 文件
注意下一个版本的 GNU coreutils (>= 8.23) 将在 od 命令中添加 --endian={little,big} 选项
我想出了这个 Perl 单行代码来将 4 字节整数从一种字节顺序转换为另一种字节顺序:
$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin > littlend.bin
这在真正的 Linux 机器上可能工作得很好,但 Cygwin 最终咬了我,将二进制文件视为文本,并在每个 0x0A 字节(又名换行符)之前插入 0x0D(又名 CR)。但如果你用管道输送到
cat -
,似乎就不管它了。这对我有用:
$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin | cat - > littlend.bin
猛击:
od -b -v -w8 | while read pfx b8 ; do [ "$b8" ] && echo -n 12345678 | tr 87654321 \\${b8// /\\} ; done
为了根据
od
的输出样式更加稳健,可能需要压缩空格(在 "| sed 's/ */ /g'"
之后插入 w8
)。
xxd
有两个标志 -e
和 -g
用于您的目的。
-e little-endian dump (incompatible with -ps,-i,-r).
-g number of octets per group in normal output. Default 2 (-e: 4).
这样,你可以:
tail -c 8 file | xxd -e -g8
一种简单的 Python 方法,每 4 个字节反转一次。使用较新的 Python 3.8+ 海象运算符:
import sys
while word := sys.stdin.buffer.read(4):
sys.stdout.buffer.write(bytes(reversed(word)))
上面的内容很简单理解,但是如果你想要更紧凑的oneliner,可以将上面的脚本修改为:
python3 -c $'import sys\nwhile word := sys.stdin.buffer.read(4):\n sys.stdout.buffer.write(bytes(reversed(word)))'
注意
$''
符号假设您正在使用 bash。它允许您在 Python 命令中使用换行符。
作为示例,在标准输入上交换一些字符:
# echo ABCDEFGH | python3 -c $'import sys\nwhile word := sys.stdin.buffer.read(4):\n sys.stdout.buffer.write(bytes(reversed(word)))'
DCBAHGFE
我发现这个命令对于将 4 字节交换为 endieness 效果很好
xxd -e 输入.bin | xxd -r > 输出_bs.bin