bash - 在 native bash 中性能合理的十六进制解码?

标签 bash

我有一个 2MB 的文件,它是由空格分隔的十六进制值序列。例如:

3F 41 56 00 00

在 Bash 中很容易做到这一点:

cat hex.txt | tr -s " " $'\n' | while read a; do 
    echo $a | xxd -r -p | tee -a ascii
done

f=$(cat hex.txt)
for a in $f; do
    echo $a | xxd -r -p | tee -a ascii
done

两者都非常慢。

我启动了一个 C 程序,它在大约两秒钟内转换了文件,后来我意识到我可以这样做:

cat hex.txt | xxd -r -p

因为我已经转换了文件并找到了最佳解决方案,所以我的问题不是关于转换过程本身,而是如何优化我的前两次尝试,就好像第三次尝试是不可能的一样。有什么办法可以加快这些单行代码的速度,还是 Bash 对此太慢了?

最佳答案

尝试以下 - 不幸的是,解决方案因 awk 而异使用的实现:

# BSD/OSX awk
xargs printf '0x%s ' < hex.txt | awk -v RS=' ' '{ printf "%c", $0 }' > ascii

# GNU awk; option -n needed to support hex. numbers
xargs printf '0x%s ' < hex.txt | awk -n -v RS=' ' '{ printf "%c", $0 }' > ascii

# mawk - sadly, printf "%c" only works with letters and numbers if the input is *hex*
awk  -v RS=' ' '{ printf "%c", int(sprintf("%d", "0x" $0)) }' < hex.txt

对于 2MB 输入文件,我的 2012 年末 iMac 配备 3.2 GHz Intel Core i5 和 Fusion Drive,运行 OSX 10.10.3 时序如下:

  • BSD/OSX awk:大约。 1s
  • GNU awk:ca。 0.6s
  • mawk:大约0.5s

将此与 PSkocik's optimized-bash-loop solution 对比:约。 11s

很容易认为 mawk解决方案,鉴于它是一个没有管道的单个命令,应该是使用all 的更快的解决方案awk实现,但实际上它不是。这是一个适用于所有三种实现的版本 -n GNU awk 按需提供:awk $([[ $(gawk --version 2>/dev/null) = GNU* ]] && printf %s -n) -v RS=' ' '{ printf "%c", int(sprintf("%d", "0x" $0)) }' < hex.txt

速度提升来自避免bash完全循环并让实用程序完成工作:

  • xargs printf '0x%s ' < hex.txthex.txt 中的所有值添加前缀与 0x这样awk稍后会将它们识别为十六进制。
    • 请注意,根据您的平台,xargs 的命令行使用所有 stdin 输入标记作为参数的构造可能超过 getconf ARG_MAX 报告的最大命令行长度- 幸运的是,xargs足够聪明,然后 多次 调用命令,每次都在命令行上安装尽可能多的参数。
  • awk -v RS=' ' '{ printf "%c", $0 }'
    • awk -v RS=' '读取每个以空格分隔的标记 - 即每个十六进制。值 - 作为单独的输入记录
    • printf "%c", $0然后使用 printf 将每条记录简单地转换为其对应的 ASCII 字符.

一般来说:

    具有大量迭代次数的
  • Bash 循环本质上很慢
  • 如果您还在每次迭代调用外部实用程序,情况会变得更糟
    请参阅下面 Charles Duffy 的评论。

为了在大量迭代次数下获得良好的性能,避免 bash 循环并让外部实用程序执行迭代工作

关于bash - 在 native bash 中性能合理的十六进制解码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30200479/

相关文章:

perl - 将环境变量导入 Perl

c++ - 在 C++ 中执行 shell 命令时强制环境 bash

bash - 在每行中查找特定单词并在 unix shell 脚本中显示结果

linux - 打破 Bash 中的嵌套函数循环

bash - 如何在 Ubuntu 的终端中自动运行应用程序?

Linux 中的 Java Jar 文件 SoftLink

linux - 如何使用 $ 和 ',' '.' 符号 bash 命令行对列进行排序?

linux - 如何利用过滤器

linux - 用于检查创建的 AMI 是否可用的脚本,

bash - 如何在没有 Readline 支持的情况下在 bash 实例中设置不区分大小写的完成