【发布时间】:2015-08-16 00:27:58
【问题描述】:
我想获取文件中的最大数字,其中数字是可以出现在文件任何位置的整数。
我想过做以下事情:
grep -o '[-0-9]*' myfile | sort -rn | head -1
这使用grep 从文件中获取所有整数,每行输出一个。然后,sort 对它们进行排序,head 打印第一个。
但后来想到sort -r可能会造成一些开销,所以我选择了:
grep -o '[-0-9]*' myfile | sort -n | tail -1
为了看看什么是最快的,我创建了一个包含一些随机数据的大文件,如下所示:
$ cat a
hello 123 how are you i am fine 42342234 and blab bla bla
and 3624 is another number
but this is not enough for -23 234245
$ for i in {1..50000}; do cat a >> myfile ; done
使文件包含 150K 行。
现在我比较GNU bash version 4.2 和sys 的性能,sort -rn 的性能要小得多:
$ time grep -o '[-0-9]*' myfile | sort -n | tail -1
42342234
real 0m1.823s
user 0m1.865s
sys 0m0.045s
$ cp myfile myfile2 #to prevent using cached info
$ time grep -o '[-0-9]*' myfile2 | sort -rn | head -1
42342234
real 0m1.864s
user 0m1.926s
sys 0m0.027s
所以我在这里有两个问题:
- 什么是最好的,
sort -r | tail -1或sort -rn | head -1? - 是否有最快的方法来获取给定文件中的最大整数?
测试解决方案
所以我运行了所有命令并比较了让它们找到值的时间。为了让事情更可靠,我创建了一个更大的文件,比我在问题中提到的文件大 10 倍:
$ cat a
hello 123 how are you i am fine 42342234 and blab bla bla
and 3624 is another number
but this is not enough for -23 234245
$ time awk -v s="$(cat a)" 'BEGIN{for (i=1;i<=500000;i++) print s}' > myfile
$ wc myfile
1500000 13000000 62000000 myfile
基准测试,我看到hek2mgl's solution 是最快的:
$ time awk 'NR==1 || max < 0+$0 {max=0+$0} END {print max}' RS='[[:space:]]+' myfile
42342234
real 0m3.979s
user 0m3.970s
sys 0m0.007s
$ time awk '{for(i=1;i<=NF;i++)if(int($i)){a[$i]=$i}}END{x=asort(a);print a[x]}' myfile
42342234
real 0m2.203s
user 0m2.196s
sys 0m0.006s
$ time awk '{for(i=1;i<=NF;i++){m=(m<$i)?$i:m}}END{print m}' RS='$' FPAT='-{0,1}[0-9]+' myfile
42342234
real 0m0.926s
user 0m0.848s
sys 0m0.077s
$ time tr ' ' '\n' < myfile | sort -rn | head -1
42342234
real 0m11.089s
user 0m11.049s
sys 0m0.086s
$ time perl -MList::Util=max -lane '$m = max $m, map {0+$_} @F} END {print $max' myfile
real 0m6.166s
user 0m6.146s
sys 0m0.011s
【问题讨论】:
-
另一个可能很快的选项:
awk -v RS="[^-0-9]+" '$0>max{max=$0}END{print max}' myfile. -
我检查了这个,它也很快,@TomFenech 不知道这里最好的是什么,将其添加到 hek2mgl 的答案中,将其保留在 cmets 中,或者添加一个新的答案它。还是谢谢!
-
@EdMorton 数字总是被空格或行首/行尾包围。它是否澄清了我的陈述?既然您提到了这种情况,那么
grep可能是这样的:grep -oE '\b-?[0-9]+'。虽然我猜还是会出现一些极端情况。
标签: performance bash sorting