【问题标题】:Why is this bash for loop slow?为什么这个 bash for 循环很慢?
【发布时间】:2013-07-13 08:42:49
【问题描述】:

我正在尝试这段代码:

for f in jobs/UPDTEST/apples* ; do
    nf=`echo $f | sed s:jobs\/::g`
    echo $nf | tr '_' ' '
done > jobs

有 750 个apples* 类型的文本文件。但因为我只是弄乱了文件名——我原以为应该很快——但大约需要 5 分钟。

有没有其他方法可以做到这一点?

【问题讨论】:

  • 你为什么不直接使用 === ls jobs/UPDTEST/apples* | sed -e 's:.*apples:apples:g;s/_/ /g' > 工作 === ?当然,您这样做的方式远非高效,至少因为您使用了很长的参数列表,并调用了“sed”和“tr”第 n 次,嵌套管道等等。你太复杂了。
  • 这很慢,因为管道的forks 很昂贵,并且每次迭代最多分叉四个进程。仅仅为了改变几个字符而分叉就像用平板卡车运送你的杂货一样。任何想要避免分叉的 shell 程序员都必须彻底了解 shell 的内置工具箱。
  • @PiotrWadas 您的建议效果很好,只需稍作改动:ls -d jobs/UPDTEST/apples* | sed -e 's:jobs\/::g;s/_/ /g' > 工作 谢谢

标签: bash for-loop


【解决方案1】:

您可以像 ${parameter/pattern/string} 一样使用 parameter expansions 来摆脱对 sedtr 的调用。在您的情况下,它可能看起来像:

for f in jobs/UPDTEST/apples*; do
    f=${f//jobs\//}
    echo ${f//_/ }
done > jobs

【讨论】:

  • 这里有各种好的答案。所以我选择这个是因为我可能会在 cmets 中使用它或 PiotrWadas 版本
【解决方案2】:

首先,cd jobs 将不再需要 sed

其次,您不需要tr 替换 bash 变量值中的字符。

第三,find 你根本不需要循环。

f=$(cd jobs; find UPDTEST -name 'apples*' -depth 1)
echo "${f//_/ }" > jobs.log

顺便说一句,jobs 目录和jobs 文件不能在同一个目录下。

【讨论】:

  • 使用f=$(cd jobs; find ...),您甚至可以保存cd ..
  • @Jens - 你是对的!我编辑我的答案以包含您的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 2014-05-17
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多