【问题标题】:More efficient way to loop through lines in shell更有效的方式来遍历 shell 中的行
【发布时间】:2017-05-04 17:07:43
【问题描述】:

我已经学会了在 bash 中循环遍历行

while read line; do stuff; done <file

这不是最有效的方法。 https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice

什么是更节省时间/资源的方法?

【问题讨论】:

  • awk(这是一个填充物)
  • 取决于stuff是调用其他shell工具,还是只是处理文本。
  • Shell if 为启动您的操作系统提供了命令并将其输入和输出管道传输到任何需要的地方。为了从文件中读取数据并对其进行处理,请使用为该特定工作制作的工具。不要将 shell 与文本处理器或编程语言混淆。
  • 您应该在需要加快循环速度的地方发布您的问题,而不是链接一个问题(答案可能有争议并取决于使用场景)。 过早的优化是万恶之源——DonaldKnuth
  • 在shell中读取文件的最有效方式。问题是,您是否应该在 shell at all 中遍历文件?一般经验法则:如果您对正在读取的数据做任何比将其作为参数传递给另一个程序更复杂的事情,那么您可能在不应该使用的情况下使用了 shell。

标签: bash performance shell loops


【解决方案1】:

正如其他人所说,这取决于你在做什么。

效率低下的原因是一切都在自己的进程中运行。取决于你在做什么,这可能是也可能不是什么大问题。

如果您想要在循环中执行的操作是运行另一个 shell 进程,那么您不会从消除循环中获得任何收益。如果您可以在不需要循环的情况下做您需要的事情,那么您可以获得收益。

【讨论】:

    【解决方案2】:

    怎么了?珀尔? C(++)?当然,这取决于您对 CPU 时间或程序员时间感兴趣,而后者取决于程序员习惯使用什么。

    您链接到的问题的最佳答案几乎解释了最大的问题是为简单的文本处理任务生成外部进程。例如。为每一行运行awk 的实例或sedcut 的管道只是为了获取字符串的一部分是愚蠢的。

    如果你想留在shell中,尽可能使用字符串处理parameter expansions${var#word}${var:n:m}${var/search/replace}等)和其他shell特性。如果您看到自己为每个输入行运行一组命令,那么是时候重新考虑脚本的结构了。大多数文本处理命令一次执行就可以处理整个文件,所以使用它。

    一个微不足道/愚蠢的例子:

    while read -r line; do
        x=$(echo "$line" | awk '{print $2}')
        somecmd "$x"
    done < file
    

    会更好

    awk < file '{print $2}' | while read -r x ; do somecmd "$x" ; done
    

    【讨论】:

    • all 处使用 awk 是错误的; read -r _ x _ 会将行拆分为必要的字段。
    • @chepner,是的,我确实说过一些关于使用 shell 功能的内容,并且我确实说过这个例子是微不足道的。 (现在加上“傻”,这是我想到的另一个词。)
    【解决方案3】:

    这是一个使用 Bash 和 awk 的 time'd 示例。我在一个文件中有 100 万条记录:

    $ wc -l 1M
    1000000 1M
    

    使用 bash 计算它的记录,使用 while read:

    $ time while read -r line ; do ((i++)) ; done < 1M ; echo $i
    
    real    0m12.440s
    user    0m11.548s
    sys     0m0.884s
    1000000
    

    使用let "i++" 耗时 15.627 秒(实际),使用do : ; 时 NOP 耗时 10.466。使用 awk:

    $ time awk '{i++}END{print i}' 1M
    1000000
    
    real    0m0.128s
    user    0m0.128s
    sys     0m0.000s
    

    【讨论】:

      【解决方案4】:

      awkperl 之间选择两者都很有效

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-30
        • 2019-11-23
        • 2021-02-28
        • 2023-03-24
        • 1970-01-01
        • 2018-12-12
        相关资源
        最近更新 更多