我有大约400'000个文件,需要更换一些文本.
我尝试了以下Perl脚本:
@files = <*.html>;
foreach $file (@files) {
`perl -0777 -i -pe 's{<div[^>]+?id="user-info"[^>]*>.*?</div>}{}gsmi;' $file`;
`perl -0777 -i -pe 's{<div[^>]+?class="generic"[^>]*>[^\s]*<small>[^\s]*Author.*?</div>.*?</div>.*?</div>.*?</div>.*?</div>}{}gsmi;' $file`;
`perl -0777 -i -pe 's{<script[^>]+?src="javascript.*?"[^>]*>.*?</script>}{}gsmi;' $file`;
`perl -p -i -e 's/.css.html/.css/g;' $file`;
}
Run Code Online (Sandbox Code Playgroud)
我没有深入的Perl知识,但脚本运行速度太慢(每天只更新大约180个文件).
有没有办法加快速度?
先感谢您!
PS:当我在少量文件上测试它时,我注意到了更好的性能......
从perl调用perl总是比在一个进程中完成所有工作要慢.所以,解决方案可能是
perl -i -pe 'BEGIN { undef $/ }
s{<div[^>]+?id="user-info"[^>]*>.*?</div>}{}gsmi;
s{<div[^>]+?class="generic"[^>]*>[^\s]*<small>[^\s]*Author.*?</div>.*?</div>.*?</div>.*?</div>.*?</div>}{}gsmi;
s{<script[^>]+?src="javascript.*?"[^>]*>.*?</script>}{}gsmi;
s/.css.html/.css/g;
' *.html
Run Code Online (Sandbox Code Playgroud)
首先,如果你将400,000个文件名加载到内存中,那将会占用一些内存.您可以通过以下方式轻松遍历文件列表:
File::Find
opendir
+ while (readdir($dh))
(不加载整个列表)其次,使用反引号会在shell中产生一个新进程,并且它非常无效.您可以正常打开文件,啜饮它们,然后重新打印到相同的文件名.例如
while (my $file = readdir($dh)) {
open my $fh, "<", $file or die $!;
local $/;
my $text = <$fh>; # slurp file
$text =~ s/....//g; # do your substitutions
open $fh, ">", $file or die $!;
print $fh $text; # overwrite file, same as -i switch does
}
Run Code Online (Sandbox Code Playgroud)
最后..使用正则表达式来编辑html并不理想.它可能适用于您的情况,但是花一些时间学习一个HTML解析器可能是值得的.不确定这种特殊情况的适用性,但可能值得研究,以使您的代码更稳定.