我有一个Perl脚本,可以在发现感兴趣的内容时分析存储文件偏移的文本文件(可以是UNIX或Windows行结尾)。
open(my $fh, $filename);
my $groups;
my %hash;
while(<$fh>) {
if($_ =~ /interesting/ ) {
$hash{$groups++}{offset} = tell($fh);
}
}
close $fh;
然后在脚本中我想生成文本文件的'n'个副本,但每个'有趣'区域都有其他内容。为了达到这个目的,我遍历了偏移的散列:
foreach my $group (keys %hash) {
my $href = $hash{$group};
my $offset = $href->{offset};
my $top;
open( $fh, $file);
read( $fh, $top, $offset);
my $bottom = do{local $/; <$fh>};
close $fh;
$href->{modified} = $top . "Hello World\n" . $bottom;
}
问题是read命令读取的字节太多。我怀疑这是一个行结束问题,因为字节数(字符?)输出与行号相同。使用Notepad ++,tell()
命令将实际偏移返回到兴趣点,但在read()
中使用该偏移值会返回超出目标点的字符。
我尝试在binmode($fh)
之前的open()
命令之后直接添加read()
。这确实在文本文件中找到了正确的位置,但随后我得到(CR + CRLF)输出并且文本文件充满了双回车。
我玩过图层:crlf,:bytes,但没有改进。
有点卡住了!
答案 0 :(得分:0)
具有连续整数范围的哈希作为键应该是一个数组。
您每次出现/interesting/
时都会存储整个文件的副本
听起来你需要做的就是这个
open(my $fh, $filename);
while (<$fh>) {
print;
print "Hello World\n" if /interesting/;
}
答案 1 :(得分:0)
来自perldoc -f read
:
read FILEHANDLE,SCALAR,LENGTH,OFFSET
read FILEHANDLE,SCALAR,LENGTH
所以,当你这样做时:
read( $fh, $top, $offset);
你的$offset
实际上是一个长度。确定需要阅读的字符数。 read
不遵循行结尾,它读取指定的字节数。
如果您想阅读一行,请不要使用read
,请使用:
seek($fh, $offset, 0);
$top = <$fh>;
您的文件是否包含两个新行,或者您是否添加了一个print
语句?
答案 2 :(得分:0)
当输入文件不是巨大的时候,我处理这个问题的标准方法是将文件插入并标准化行结尾,将每一行存储为数组元素。我有时不得不在同一批文件中处理Windows(CR
+ LF
)和UNIX(仅LF
)和Mac(仅CR
)行结尾。同样的脚本也需要在所有三个平台上正确运行。
当我不得不处理这些事情时,我通常采取腰带和括号的方法。一种应该工作的方式:
sub read_file_into_array
{
my $file = shift;
my ($len, $cnt, $data, @file);
open my $fh, "<", $file or die "Can't read $file: $!";
seek $fh, 0, 2 or die "Can't seek $file: $!";
$len = tell $fh;
seek $fh, 0, 0 or die "Can't seek $file: $!";
$cnt = read $fh, $data, $len;
close $fh;
$cnt == $len or die "Attempted to read $len bytes; got $cnt";
$data =~ s/\r\n/\n/g; # Convert DOS line endings to UNIX
$data =~ s/\r/\n/g; # Convert Mac line endings to UNIX
@file = split /\n/, $data; # Split on UNIX line endings
return \@file;
}
然后对@file
中的行进行所有处理。对于“有趣”标记,您将存储数组索引而不是文件偏移量。数组索引本质上是原始文件中的行号,从0开始计数而不是1。
要实际扩充文件,而不是循环遍历散列键,为什么不构造一个由line-number =&gt;组成的散列。 thing-to-append对,生成如下的增强文件:
sub generate_augmented_file
{
my $file = shift @_; # array ref
my $extras = shift @_; # hash ref of line => extra pairs
my $text;
foreach my $line ( 0 .. scalar( $file ) - 1 )
{
$text .= $file->[$line];
$text .= $extras->{$line} if defined $extras->{$line};
$text .= "\n";
}
return $text;
}