od(1) 的相反数是什么?

发布于 2024-07-17 09:02:03 字数 177 浏览 13 评论 0原文

假设我有

8b1f 0008 0231 49f6 0300 f1f3 75f4 0c72 f775 0850 7676 720c 560d 75f0 02e5 ce00 0861 1302 0000 0000

如何轻松地从中获取二进制文件,而无需复制+粘贴到十六进制编辑器中?

Say I have

8b1f 0008 0231 49f6 0300 f1f3 75f4 0c72 f775 0850 7676 720c 560d 75f0 02e5 ce00 0861 1302 0000 0000

How can I easily get a binary file from that without copying+pasting into a hex editor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

野心澎湃 2024-07-24 09:02:03

使用:

% xxd -r -p in.txt out.bin

Use:

% xxd -r -p in.txt out.bin
梦屿孤独相伴 2024-07-24 09:02:03

请参阅xxd

See xxd.

长梦不多时 2024-07-24 09:02:03

目前的所有答案都指的是方便的 xxd -r 方法,但对于 xxd 不可用或不方便的情况,这里是一种更可移植(并且更灵活,但更详细)的方法并且效率较低)解决方案,仅使用 POSIX shell 语法(它还补偿输入中的奇数位数):

un_od() {
    printf -- "$(
        tr -d '\t\r\n ' |
          sed -e 's/^\(.\(.\{2\}\)*\)$/0\1/' -e 's/\(.\{2\}\)/\\x\1/g'
    )"
}

顺便说一句:您没有指定您的输入是大端还是小端,或者您是否想要大/小端输出。 通常,您的问题中的输入将是大端/网络顺序(例如,由 od -t x1 -An -v 创建),并且预计会转换为大端输出。 我认为 xxd 只是假设默认值(如果没有另外告知的话),并且此解决方案也这样做。 如果需要字节交换,如何进行字节交换还取决于系统的字大小(例如,32 位、64 位),并且非常很少取决于字节大小(您可以几乎总是假设 8 位字节(八位字节)。

以下函数使用更复杂的二进制版本 -> OD-> 二进制技巧可移植字节交换二进制数据,以系统字节顺序为条件,并考虑系统字大小。 该算法适用于任何高达 72 位字大小的内容(因为 seq -s '' 10 -> 12345678910 不起作用):

if { sed --version 2>/dev/null || :; } | head -n 1 | grep -q 'GNU sed'; then
    _sed() { sed -r "${@}"; }
else
    _sed() { sed -E "${@}"; }
fi

sys_bigendian() {
    return $(
        printf 'I' | od -t o2 | head -n 1 |
            _sed -e 's/^[^ \t]+[ \t]+([^ \t]+)[ \t]*$/\1/' | cut -c 6
    )
}

sys_word_size() { expr $(getconf LONG_BIT) / 8; }

byte_swap() {
    _wordsize=$1
    od -An -v -t o1 | _sed -e 's/^[ \t]+//' | tr -s ' ' '\n' |
        paste -d '\\' $(for _cnt in $(seq $_wordsize); do printf -- '- '; done) |
        _sed -e 's/^/\\/' -e '$ s/\\+$//' |
        while read -r _word; do
            _thissize=$(expr $(printf '%s' "$_word" | wc -c) / 4)
            printf '%s' "$(seq -s '' $_thissize)" | tr -d '\n' |
                tr "$(seq -s '' $_thissize -1 1)" "$_word"
        done
    unset _wordsize _prefix _word _thissize
}

您可以使用上面的无论系统字节顺序如何,都以大端格式输出文件内容:

if sys_bigendian; then
    cat /bin/sh
else
    cat /bin/sh | byte_swap $(sys_word_size)
fi

All the present answers refer to the convenient xxd -r approach, but for situations where xxd is not available or convenient here is a more portable (and more flexible, but more verbose and less efficient) solution, using only POSIX shell syntax (it also compensates for odd-number of digits in input):

un_od() {
    printf -- "$(
        tr -d '\t\r\n ' |
          sed -e 's/^\(.\(.\{2\}\)*\)$/0\1/' -e 's/\(.\{2\}\)/\\x\1/g'
    )"
}

By the way: you don't specify whether your input is big-endian or little-endian, or whether you want big/little-endian output. Usually input such as in your question would be big-endian/network-order (e.g., as created by od -t x1 -An -v), and would be expected to transform to big-endian output. I presume xxd just assumes that default if not told otherwise, and this solution does that too. If byte-swapping is needed, how you do the byte-swapping also depends on the word-size of the system (e.g., 32 bit, 64 bit) and very rarely the byte-size (you can almost always assume 8-bit bytes - octets - though).

The below functions use a more complex version of the binary -> od -> binary trick to portably byteswap binary data, conditional on system endianness, and accounting for system word-size. The algorithm works for anything up to 72-bit word size (because seq -s '' 10 -> 12345678910 doesn't work):

if { sed --version 2>/dev/null || :; } | head -n 1 | grep -q 'GNU sed'; then
    _sed() { sed -r "${@}"; }
else
    _sed() { sed -E "${@}"; }
fi

sys_bigendian() {
    return $(
        printf 'I' | od -t o2 | head -n 1 |
            _sed -e 's/^[^ \t]+[ \t]+([^ \t]+)[ \t]*$/\1/' | cut -c 6
    )
}

sys_word_size() { expr $(getconf LONG_BIT) / 8; }

byte_swap() {
    _wordsize=$1
    od -An -v -t o1 | _sed -e 's/^[ \t]+//' | tr -s ' ' '\n' |
        paste -d '\\' $(for _cnt in $(seq $_wordsize); do printf -- '- '; done) |
        _sed -e 's/^/\\/' -e '$ s/\\+$//' |
        while read -r _word; do
            _thissize=$(expr $(printf '%s' "$_word" | wc -c) / 4)
            printf '%s' "$(seq -s '' $_thissize)" | tr -d '\n' |
                tr "$(seq -s '' $_thissize -1 1)" "$_word"
        done
    unset _wordsize _prefix _word _thissize
}

You can use the above to output file contents in big-endian format regardless of system endianness:

if sys_bigendian; then
    cat /bin/sh
else
    cat /bin/sh | byte_swap $(sys_word_size)
fi
枯寂 2024-07-24 09:02:03

此版本也适用于二进制格式:

cat /bin/sh \
| od -A n -v -t x1 \
| tr -d '\r' \
| xxd -r -g 1 -p1 \
| md5sum && md5sum /bin/sh

额外的“\r”仅适用于 DOS 文本文件...
并逐字节处理,以防止在不同系统上运行管道的各个部分时出现字节序差异。

This version will work with binary format too:

cat /bin/sh \
| od -A n -v -t x1 \
| tr -d '\r' \
| xxd -r -g 1 -p1 \
| md5sum && md5sum /bin/sh

The extra '\r' is just if you're dealing with DOS text files...
And process byte by byte to prevent endianness difference if running parts of a pipe on different systems.

不必了 2024-07-24 09:02:03

这是反转“od”输出的方法:

echo "test" | od -A x -t x1 | sed -e 's|^[0-f]* ?||g' | xxd -r
test

Here is the way to reverse "od" output:

echo "test" | od -A x -t x1 | sed -e 's|^[0-f]* ?||g' | xxd -r
test
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文