【问题标题】:Convert binary data to hexadecimal in a shell script在 shell 脚本中将二进制数据转换为十六进制
【发布时间】:2011-06-09 12:16:45
【问题描述】:

我想将二进制数据转换为十六进制,仅此而已,没有花哨的格式等等。 hexdump 似乎太聪明了,对我来说它“过度格式化”。我想从 /dev/random 中取出 x 个字节并将它们作为十六进制传递。

我最好只使用标准的 Linux 工具,这样我就不需要在每台机器上都安装它(有很多)。

【问题讨论】:

  • 我不得不使用 /dev/urandom,/dev/random 只是冻结了
  • @AquariusPower 在没有足够随机数据时随机阻塞,而 urandom 没有(IIRC 循环遍历它所拥有的数据)

标签: linux scripting hexdump


【解决方案1】:

也许用xxd:

% xxd -l 16 -p /dev/random
193f6c54814f0576bc27d51ab39081dc

【讨论】:

  • xxd 是 vim 的一部分,所以它可能并不总是被安装。
  • 请注意,您可以使用-c 更改每行的字节数。不幸的是,您只能将其设置为 256,之后您需要添加一些换行符。
  • 我只想说声谢谢,这是我见过的最快的生成数据而无需做过多工作的方法。我确实在几秒钟内完成了一个 2gb 的文件我需要 32 字节的十六进制字符串,这成功了time xxd -c 32 -l 1024000000 -ps /dev/urandom 32bytehexnewtest1.txt ; real 0m17.484s
【解决方案2】:

小心!

hexdumpxxd 以不同的字节序给出结果!

$ echo -n $'\x12\x34' | xxd -p
1234
$ echo -n $'\x12\x34' | hexdump -e '"%x"'
3412

Simply explained. Big-endian vs. little-endian :D

【讨论】:

  • 使用echo -n $'\x12\x34' | hexdump -e '/1 "%x"' 获得相同的字节序。
  • 还要小心! hexdump 将去除前导零。
【解决方案3】:

使用od(GNU 系统):

$ echo abc | od -A n -v -t x1 | tr -d ' \n'
6162630a

使用hexdumpBSD 系统):

$ echo abc | hexdump -ve '/1 "%02x"'
6162630a

来自Hex dump, od and hexdump

“根据您的系统类型,这两个实用程序中的一个或两个都将可用--BSD 系统不推荐使用 hexdump 的 od,而 GNU 系统则相反。”

【讨论】:

  • 4 年后(我知道不多),大多数时候我阅读有关 *nix 的帖子,我了解到一些非常古老但对我来说仍然全新的东西。 +1 为 od,从未听说过,非常有用,甚至在 Cygwin 上也存在。 ;-)
【解决方案4】:

也许您可以用 C 编写自己的小工具,并即时编译它:

int main (void) {
  unsigned char data[1024];
  size_t numread, i;

  while ((numread = read(0, data, 1024)) > 0) {
    for (i = 0; i < numread; i++) {
      printf("%02x ", data[i]);
    }
  }

  return 0;
}

然后从标准输入中输入:

cat /bin/ls | ./a.out

您甚至可以使用 heredoc 语法将这个小型 C 程序嵌入到 shell 脚本中。

【讨论】:

  • C,为了这个?这有点过头了。
  • 好吧,但是您可以完全控制格式和行为 :-)
  • 这总是一个选择,但我很确定它之前已经解决了:)
  • @user405725 - 这似乎是 C 程序员最简单的解决方案。据我所知,所有其他解决方案都 not 对二进制文件进行十六进制编码。我对这项任务变得多么困难感到困惑。对二进制文件进行十六进制编码真的很难吗?
  • 难以置信,但这可能是这个问题的最佳答案。
【解决方案5】:

所有解决方案似乎都难以记忆或过于复杂。我发现使用printf 是最短的:

$ printf '%x\n' 256
100

但正如 cmets 所述,这不是作者想要的,所以公平地说,下面是完整的答案。

...使用上面输出实际的二进制数据流:

printf '%x\n' $(cat /dev/urandom | head -c 5 | od -An -vtu1)

它的作用:

  • printf '%x\n' .... - 打印整数序列,即printf '%x,' 1 2 3,将打印1,2,3,
  • $(...) - 这是一种获取某些 shell 命令输出并对其进行处理的方法
  • cat /dev/urandom - 它输出随机二进制数据
  • head -c 5 - 将二进制数据限制为 5 个字节
  • od -An -vtu1 - 八进制转储命令,将二进制转换为十进制

作为测试用例('a' 是 61 hex,'p' 是 70 hex,...):

$ printf '%x\n' $(echo "apple" | head -c 5 | od -An -vtu1)
61
70
70
6c
65

或者为了测试单个二进制字节,在输入时让我们给出 61 个十进制数('=' char)来生成二进制数据('\\x%x' 格式就可以了)。上述命令会正确输出3d(十进制61):

$printf '%x\n' $(echo -ne "$(printf '\\x%x' 61)" | head -c 5 | od -An -vtu1)
3d

【讨论】:

  • @МалъСкрылевъ 我已经更新了我的答案,你是对的,我错过了问题的要点 - 我可能正在寻找在 shell 中将十进制转换为十六进制的最简单方法,这个答案出现在谷歌中首先。
  • 嘿,我知道这是旧的,但对于第二个密码框,你不能跳过猫直接做头部吗? printf '%x\n' $(head -c 5 /dev/urandom | od -An -vtu1) 或者 cat 命令是否有特定原因?另外,如果你想让十六进制最后只用一个新行分隔,我想出了这个echo $(printf "%x" $(head -c 5 /dev/urandom | od -An -vtu1)),虽然我不知道这些的性能成本,主要是为什么我问关于 cat 命令被删掉的原因。我对命令行很陌生,但这些信息都有帮助。
  • @cigolon head 比 cat 好。我经常使用time 命令来衡量命令的性能。
  • 这就是我问这个的原因。 printf '%x\n' $(cat /dev/urandom | head -c 5 | od -An -vtu1) VS printf '%x\n' $(head -c 5 /dev/urandom | od -An -vtu1) 没有 cat 管道的第二个命令总体上要快一些。
【解决方案6】:

如果您需要大流(无换行符),您可以使用 trxxd(Vim 的一部分)进行逐字节转换。

head -c1024 /dev/urandom | xxd -p | tr -d $'\n'

或者您可以使用hexdump (POSIX) 进行逐字转换。

head -c1024 /dev/urandom | hexdump '-e"%x"'

注意区别在于字节序。

【讨论】:

  • 使用echo abc | hexdump -e '/1 "%02x"' 获取网络顺序和0x0a 的0。
【解决方案7】:

dd + hexdump 也可以:

dd bs=1 count=1 if=/dev/urandom 2>/dev/null  | hexdump -e '"%x"'

【讨论】:

  • 谢谢,我是这样开始的,但无法让 hexdump 做我想做的事。我很确定它有我需要的选项,但在手册页中找不到它
  • 使用此解决方案 (hexdump -e '"%x"'): '\n' -> 'a' (缺少前导 '0'), 'abcde' -> '6463626165' (不正确字节顺序)。这在非随机数据应用程序中可能非常糟糕!
【解决方案8】:

这三个命令将打印相同的(0102030405060708090a0b0c):

n=12
echo "$a" | xxd -l "$n" -p
echo "$a" | od  -N "$n" -An -tx1 | tr -d " \n" ; echo
echo "$a" | hexdump -n "$n" -e '/1 "%02x"'; echo

假设n=12$a 是从1 到26 的字节值:

a="$(printf '%b' "$(printf '\\0%o' {1..26})")"

这可用于在每个程序中获取$n 随机字节值:

xxd -l "$n" -p                   /dev/urandom
od  -vN "$n" -An -tx1            /dev/urandom | tr -d " \n" ; echo
hexdump -vn "$n" -e '/1 "%02x"'  /dev/urandom ; echo

【讨论】:

    【解决方案9】:

    如果您针对多个平台,有时 perl5 的可移植性会更好。它随每个 Linux 发行版和 Unix 操作系统一起提供。您通常可以在容器映像中找到它,而其他工具(如 xxd 或 hexdump)不可用。下面是如何在 Perl 中做同样的事情:

    $ head -c8 /dev/urandom | perl -0777 -ne 'print unpack "H*"'
    5c9ed169dabf33ab
    
    $ echo -n $'\x01\x23\xff' | perl -0777 -ne 'print unpack "H*"'
    0123ff
    
    $ echo abc | perl -0777 -ne 'print unpack "H*"'
    6162630a
    

    请注意,这会更多地使用 slurp,这会导致 Perl 将整个输入读入内存,当输入很大时,这可能不是最佳的。

    【讨论】:

      猜你喜欢
      • 2013-09-23
      • 2010-09-27
      • 2012-10-28
      • 2012-06-26
      • 2016-05-21
      • 1970-01-01
      • 2016-08-28
      相关资源
      最近更新 更多