前言:
我一直被教导在shell中工作时,最好使用while
循环而不是for
循环,并且不要使用for
循环与命令替换cat
文件。我的理解是有许多原因,包括:
for
循环需要一次性将所有要处理的数据加载到内存中for
循环默认情况下对空格进行单词分割,而不是换行符,因此除了必须将所有输入文件都放入内存中外,还会进行更多的单词分割从而占用更多的内存for
循环在您的in
语句完成加载之前不会开始处理“do右侧”的内容,这意味着在等待结果的部分时间内,实际上没有任何事情正在发生,而是在“预加载”。
然而,在进行一些简单的测试后,我发现虽然内存消耗在for
循环中似乎更大(这是可以预料的),但while
循环的实际性能较低。这并不是一个巨大的差异,在任何现代计算机上可能开始变得重要的规模上,我可能会切换到awk或python,但我仍然很好奇为什么会发生这种情况。
测试设置:
我进行了一系列简单的测试,只是将文件中的行回显到/dev/null中。我的输入是包含100K和1Mil IP地址的两个平面文件。在下面的输出中,有一个测试,但我多次运行了此测试,并且每次结果都类似。我在2013 MBA(i7,8g Mem)上运行了此测试。
测试结果
Ds-MacBook-Air:~ d$ time for i in $(cat /tmp/ips.100k);do echo $i > /dev/null;done
real 0m1.629s
user 0m1.154s
sys 0m0.480s
Ds-MacBook-Air:~ d$ time for i in $(cat /tmp/ips.mill);do echo $i > /dev/null;done
real 0m17.567s
user 0m12.414s
sys 0m5.131s
Ds-MacBook-Air:~ d$ time while read i;do echo $i > /dev/null;done < /tmp/ips.100k
real 0m2.148s
user 0m1.493s
sys 0m0.655s
Ds-MacBook-Air:~ d$ time while read i;do echo $i > /dev/null;done < /tmp/ips.mill
real 0m21.536s
user 0m14.915s
sys 0m6.617s
Ds-MacBook-Air:~ d$ tail -5 /tmp/ips.100k /tmp/ips.mill
==> /tmp/ips.100k <==
1.1.134.155
1.1.134.156
1.1.134.157
1.1.134.158
1.1.134.159
==> /tmp/ips.mill <==
1.15.66.59
1.15.66.60
1.15.66.61
1.15.66.62
1.15.66.63
Ds-MacBook-Air:~ d$ wc -l /tmp/ips.100k /tmp/ips.mill
100000 /tmp/ips.100k
1000000 /tmp/ips.mill
1100000 total
关于 for
循环和 while
循环的区别,我没有直接引用的资料,但我记得在《TLDP》Wooldridge文档或其他Bash编程指南中有详细介绍(一些快速的谷歌搜索并没有找到我几年前读到这些内容的确切位置)。
$(<testfile)
是$(cat testfile)
的更高效替代品。 - Charles Duffy...; done >/dev/null
会有影响吗? - tripleee