bash 字符串操作速度与管道

bash 字符串操作速度与管道

我有一个充满 md5 校验和和文件名的文件。我需要对每一行执行一些处理,所以我需要知道:

  • 哪个是校验和
  • 文件名是哪个

并采取相应行动。也就是说,我需要将校验和放入变量中,然后是文件名。文件名中可能包含非 ASCII 字符,但我不希望看到换行符。它看起来像这样:

05c00367e8914ca1be0964821d127977  ./.fseventsd/0000000000097aa1
cd9d4291f59a43c0e3d73ff60a337bb5  ./.fseventsd/00000000000fdfec
5d1280769e741e04622cfd852f33a138  ./.fseventsd/0000000000103197
8dda3534e5bbc0be1d15db2809123c50  ./.fseventsd/000000000017c9ca
(...etc., about 100,000 lines)

传统上,我可能会执行这样的操作:

md5sum=$(echo $line | awk '{print $1}')
filename=$(echo $line | sed 's/[^ ]*  //')

但如果我这样做的话会快多少:

md5sum=${line%%" "*}
filename=${line#*"  "}

答案1

是的,使用 bash 内部命令可以避免许多系统调用。尤其是有递归的时候。

另一个例子:我们必须使用 * 来对抗 $(ls)。

Bash 提供了一些对字符串进行简单操作的方法(剪切和替换)。但仅此而已。因为它不是为此而设计的。示例:在没有外部命令的情况下很难验证字符串中模式的存在。

外部程序针对其任务进行了更优化(cat、sed、grep、awk、cut、sort...)

答案2

我通过设置其中一个变量进行测试。执行此脚本两次:

while read line; do
        md5sum=${line%%" "*}
        #md5sum=$(echo $line | awk '{print $1}')
        echo "SUM: $md5sum FILE:_$file"
done < manifest.Stuph.180620

首先与

md5sum=${line%%" "*}

接下来是

md5sum=$(echo $line | awk '{print $1}')

其中文件“manifest.Stuph.180620”的长度为 100939 行(== 约 14MiB),结果如下:

第一次运行(使用 bash 的内置字符串操作)

real    0m4.750s
user    0m4.174s
sys     0m0.550s

第二次运行(使用管道)

real    10m54.255s
user    4m42.257s
sys     7m32.880s

有些人(例如我自己)会说,如果速度很重要,那么您无论如何都不应该在 shell 中乱搞,但有时您可能希望提高效率 - 无论您使用什么环境来完成工作。

请注意,这样做:

while read md5sum filename; do
    (...etc...)

甚至比进行变量赋值更有效,但还没有达到消除命令替换/管道/awk 构造的程度。我发现最有趣的是 bash 内置性能和使用外部命令之间的差异。我会更加勤奋地学习和使用精美的内置东西!

相关内容