我写了一个小小的perl单行:
find . -name '*.cpp' -print0 2>/dev/null | xargs -0 -i perl -ne 'if (/\+\+\S*[cC]ursor\S*/ && !/[!=]=\s*DB_NULL_CURSOR/) {print "$ARGV:$.\n $_\n";}' {}
在我正在运行的目录中,find
部分返回5802个结果。
现在,我理解xargs -i
(或-n1
)会对性能产生影响,但是使用-i
:
find . -name '*.cpp' -print0 2> /dev/null 0.33s user 1.12s system 0% cpu 3:12.57 total
xargs -0 -i perl -ne {} 4.12s user 32.80s system 16% cpu 3:42.22 total
没有:
find . -name '*.cpp' -print0 2> /dev/null 0.27s user 1.22s system 95% cpu 1.556 total
xargs -0 perl -ne 0.62s user 0.69s system 61% cpu 2.117 total
分钟与几秒钟(测试的顺序确定无关紧要)。除了在第二种情况下显然不正确的行号之外,实际的perl结果是相同的。
Cygwin / bash / perl5v26和WSL Ubuntu 16.04 / zsh / perl5v22中的行为相同。两种情况下文件系统都是NTFS。但是......我有点假设我写的小单行必须有一些错误,那些东西是无关紧要的?
编辑:我发现在启动时使用-f
禁用sitecustomize.pl - 我隐约记得用perl --help
看到的选项 - 可能会有所帮助。它没。此外,我知道由于perl编译正则表达式,-i
的性能影响将会很大。这似乎仍然失控。
好吧,我的根本误解是假设最大命令行长度在2000范围内。所以我假设每20个文件左右一个perl实例(每个大约120个字符)。这非常不正确。
getconf ARG_MAX
显示实际可接受的长度。就我而言:
2097152
所以,我正在研究1个perl实例与5802个实例。我能想到的唯一的perl解决方案是删除-n
并手动实现循环,显式关闭每个文件。
我认为更好的解决方案是awk:
find . -name '*.cpp' 2>/dev/null -print0 | xargs -0 awk '{if (/\+\+\S*[cC]ursor\S*/ && !/[!=]=\s*DB_NULL_CURSOR/) {print FILENAME ":" FNR " " $0}}'
或者grep:
find . -name '*.cpp' 2>/dev/null -print0 | xargs -0 grep -nE '\+\+\S*[cC]ursor\S*' | grep -v '[!=]=\s*DB_NULL_CURSOR'
两者都在2或3秒范围内执行。