BASH:如何将 for 循环生成的值快速写入文件

Jac*_*cek 2 io bash

我在 bash 中有一个 for 循环,可以将值写入文件。不过因为值比较多,所以过程比较耗时,我觉得可以通过改进代码来节省。

nk=1152
nb=24

for k in $(seq 0 $((nk-1))); do
    for i in $(seq 0 $((nb-1))); do
        for j in $(seq 0 $((nb-1))); do
            echo -e "$k\t$i\t$j" 
        done
    done
done > file.dat
Run Code Online (Sandbox Code Playgroud)

我已将输出操作移至整个循环完成后,而不是echo -e "$k\t$i\t$j" >> file.dat避免多次打开和关闭文件。但是,脚本写入文件的速度仍然很慢,大约 10kbps。

有没有更好的方法来改善 IO?

非常感谢 Jacek

tad*_*man 6

seq由于这是一个单独的过程,因此这些电话看起来相当严厉。试试这个,只使用 shell 数学:

for ((k=0;k<=$nk-1;k++)); do
    for ((i=0;i<=$nb-1;i++)); do
        for ((j=0;j<=$nb-1;j++)); do
            echo -e "$k\t$i\t$j" 
        done
    done
done > file.dat
Run Code Online (Sandbox Code Playgroud)

在我的机器上只需要 7.5 秒。

另一种方法是只计算一次序列并重复使用它们,从而节省大量的 shell 调用:

    nk=1152
    nb=24

    kseq=$(seq 0 $((nk-1)))
    bseq=$(seq 0 $((nb-1)))

    for k in $kseq; do
        for i in $bseq; do
            for j in $bseq; do
                echo -e "$k\t$i\t$j" 
            done
        done
    done > file.dat
Run Code Online (Sandbox Code Playgroud)

这并不比第一个选项“更好”,但它显示了花在旋转实例上的时间seq与实际完成工作的时间。

Bash 并不总是最好的。考虑在 0.5 秒内运行的这个 Ruby 等价物:

#!/usr/bin/env ruby

nk=1152
nb=24

nk.times do |k|
  nb.times do |i|
    nb.times do |j|
      puts "%d\t%d\t%d" % [ k, i, j ]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)