Bash awk在4GB文件上的运行时间/性能
我已经写了一个脚本,它给了我一个模式后的下一行(我需要的行在上面一行和下面一行的46次“=”之间)和该行的行号。在那之后,我做了一个sed来格式化它,所以我只剩下46*'='之间的一行。我把它写进一个文件,这样我可以进一步处理它 我从中得到的文件非常小,最多有30个匹配项 我是从这个开始的Bash awk在4GB文件上的运行时间/性能,bash,performance,awk,sed,Bash,Performance,Awk,Sed,我已经写了一个脚本,它给了我一个模式后的下一行(我需要的行在上面一行和下面一行的46次“=”之间)和该行的行号。在那之后,我做了一个sed来格式化它,所以我只剩下46*'='之间的一行。我把它写进一个文件,这样我可以进一步处理它 我从中得到的文件非常小,最多有30个匹配项 我是从这个开始的 awk '/^\={46}$/{ n=NR+1 } n>=NR {print NR","$0}' $file1 | sed -n '2~4p' > tmpfile$1 但是 4 GB文件需要11
awk '/^\={46}$/{ n=NR+1 } n>=NR {print NR","$0}' $file1 | sed -n '2~4p' > tmpfile$1
但是4 GB文件需要115秒,1 GB文件需要12秒,100 MB文件需要2秒 我注意到所有文件的最后一个匹配总是相同的,但在文件本身中是唯一的,所以我在一个出口中工作。最后一次匹配发生在大约50k-500k行之后,之后还有6700万行用于4 GB文件(最后一次匹配为71k),2600万行用于1 GB文件(最后一次匹配为168k),200万行用于100 MB文件(最后一次匹配为414k) 我得到的次数是:
4 GB文件需要70秒,1 GB文件需要2秒,100 MB文件需要1秒
这是一个进步 我还试着点了另一道菜
awk '1;/*unique string here*/{exit}' $file1 | awk '/^\={46}$/{ n=NR+1 } n>=NR {print NR","$0}' | sed -n '2~4p > tmpfile$1
并且得到了在4GB文件上需要70秒,在1GB文件上需要5秒,在100MB文件上需要1秒 现在,虽然在awk中有一个出口是一种改进,但考虑到上次匹配发生的时间,我希望4GB文件有更好的性能。至少当我看到使用1GB文件节省了多少时间时。
由于1GB文件的第三个awk比第二个awk慢,但4GB文件的速度相同,我想我遇到了一些内存问题,因为4GB文件太大了,我只是使用了一个带有2个CPU和4GB RAM的Ubuntu虚拟机 这是我第一次使用awk、sed和脚本,所以我不知道现在该怎么做才能更好地使用4GB文件。我对1GB文件的2秒时间没有意见 输入/输出示例
Random text here
blab
==============================================
Here is the string I need
==============================================
------------------------
random stuff
------------------------
other stuff
==============================================
Here is the 2nd string I need
==============================================
i dont need this string here
Random stuff
==============================================
last string I need, that is the same across all files
==============================================
a lot of lines are following the last match
输出:
5,Here is the string I need
15,Here is the 2nd string I need
22,last string I need, that is the same across all files`
edit1:将在周一更新并尝试一些新的东西(用更多的ram构建一个类似的虚拟机)
edit2:在启动了一个新的vm,并对更大的文件(大约15GB)进行了更多的测试,并将缓存作为一个因素,之后,我没有注意到在这里发布的所有不同代码的运行时中有任何大的变化
但是flag on,flag off{f=!f;next}确实比我的代码优雅得多,所以感谢James Brown和Ed Morton。如果可以,我会选择你的两个答案:)这个怎么样:
$ awk '/^\={46}$/ {f=!f; next} f {print NR, $0}' file
5 Here is the string I need
15 Here is the 2nd string I need
22 last string I need, that is the same across all files
=
s字符串向上翻转标志f
,然后打印,直到下一个向下翻转标志的字符串为止。使用awk时,您永远不需要sed。您不需要转义=
,因为它不是元字符。字符串连接很慢。Regexp比较比字符串比较慢。测试n>=NR
没有意义,因为n
对于您不想要的=*
行只大于NR
。您当前正在打印每==行之后的行,但您只需要两行之间的行。如果“唯一字符串”是要打印的行之一,则只需在打印位置进行测试,而不是针对文件中的每一行。尝试:
$ awk -v OFS=',' '
$0=="=============================================="{f=!f; next}
f {print NR, $0; if (/unique string/) exit}
' file
5,Here is the string I need
15,Here is the 2nd string I need
22,last string I need, that is the same across all files
要了解regexp比较的不同之处,您也可以尝试以下方法:
awk -v OFS=',' '
/^={46}$/{f=!f; next}
f {print NR, $0; if (/unique string/) exit}
' file
即使不强迫awk计算46个=
也可能更快:
awk -v OFS=',' '
/^=+$/{f=!f; next}
f {print NR, $0; if (/unique string/) exit}
' file
提供示例输入和输出。我在opow long does
grep-A1^===========================文件
处理您的文件?您使用的是本地驱动器还是网络驱动器?grep需要0,03秒-0,5秒-35,3秒(100MB-1GB-4GB)。起初我也用grep尝试过,但是输出不够一致。我不确定这个驱动器,它应该是一个网络化的,具有更大的RAID10。是的,它工作正常,输出看起来比我写的更好,我不需要管道sed,但就它需要的时间而言:1,5秒-11,6秒-108,8秒(100 MB-1GB-4 GB),如果我输入/*我需要的最后一个字符串,所有文件都是一样的*/{exit}
它需要1,2秒-4,5秒-71秒。这是否更快:awk'/^\={46}$/{getline;print NR,$0;getline;next}'文件
`1,3 s-11,5 s-106s@damnthisishard-Awk可能将行拆分为$1、$2、,。。。即使你只会使用0美元。也许可以尝试将换行符设置为分隔符以防止拆分?示例:awk-F'\n“awk code here'
附加问题:假设只需要一行,它夹在一对==
s之间,使用getline
是否可以,以及使用flag在性能wrt方面如何比较?例如:$0==”{getline;print NR,$0;if(/last string/)exit;getline}
No,因为它会引入所有需要担心的getline警告(请参阅),并且不会提高性能,因为通过引入getline successif((getline line)>0),您避免了对f
的测试。您无法测试getline成功,或者您可能正在打印没有警告或错误消息的垃圾。谢谢,如果我有进一步的疑问,将检查它并返回给您:)我已经创建了足够大的示例输入,使用getline的输入稍微快一些(对于17M文件,大约0.030秒)好的,您可能已经知道了这一点,但在计时时,请确保每个命令运行3次,然后比较每个命令的第3次结果,以删除缓存,这可能是性能差异的原因。嗯,我不知道缓存,所以我以前所有的时间似乎都不可用(在另一轮测试之后,令人遗憾的是,情况似乎是这样)。在尝试新东西之前,我必须先阅读这篇文章
awk -v OFS=',' '
/^=+$/{f=!f; next}
f {print NR, $0; if (/unique string/) exit}
' file