我想知道是否有一种有效的方法可以删除文件中的第一行(如果它与指定的模式匹配)。例如,我有一个包含以下格式数据的文件:
Date,Open,High,Low,Close,Volume,Adj.Volume
2012-01-27,42.38,42.95,42.27,42.68,2428000,42.68
2012-01-26,44.27,44.85,42.48,42.66,5785700,42.66
.
.
.
我想删除第一行,只要它包含文本(如第一行中的示例所示),如果它只包含数字(如其余行中所示),则保持不变。这项任务非常简单,我已经通过应用以下代码安静来完成它,只要代码不包含$newFile
模式,就会将每行写入Date
:
while( <$origFile> )
{
chomp($_);
print $newFile $_ unless ($_ =~ m/Date/g)
}
正如我所提到的,这使得工作完成了。但是,当知道文本只出现在第一行时,读取整个文件中的每一行似乎是浪费资源。
有没有办法更有效地完成这项任务?
注意:我已经找到了一个几乎相似的问题here,但由于我希望我的代码在Linux和Windows上也可用,因此使用sed
对我没有帮助。
提前致谢!
答案 0 :(得分:3)
$.
可用于确定是否正在处理文件的第一行。
perl -i.bak -ne'print if $. != 1 || !/^Date/;' file
然而,在整个文件中读取每一行似乎浪费了很多资源
除了文件末尾之外的任何地方都无法删除。要从开头或中间删除,需要移动文件中后面的所有内容,这意味着必须同时读取和写入。
如果第一行不匹配(通过什么都不做),你只能避免工作。如果您需要删除该行,则必须复制整个文件。
答案 1 :(得分:2)
Tie::File模块非常适用于此。它非常有效,因为它阻止IO而不是一次读取一行,这使得程序编写起来非常简单。
use strict;
use warnings;
use Tie::File;
tie my @data, 'Tie::File', 'mydatafile' or die $!;
shift @data if $data[0] =~ /Date/;
untie @data;
答案 2 :(得分:1)
只在第一行进行测试,然后只检查文件的其余部分而不检查:
if (defined( $_ = <$origFile> )) {
if ( ! m/Date/o ) { print $newFile $_ }
my $data;
for (;;) {
my $readRes = read($origFile, $data, 0x10000);
if (!defined $readRes) { die "Can't read: $!" }
if ($readRes == 0) { last }
print $newFile $data;
}
}