Perl读取、查找和告诉文本文件。正在读取的字节太多。层和换行处理
我有一个Perl脚本,它分析一个文本文件(可以是UNIX或windows的行尾),当它找到感兴趣的内容时,存储文件偏移量Perl读取、查找和告诉文本文件。正在读取的字节太多。层和换行处理,perl,seek,tell,binmode,Perl,Seek,Tell,Binmode,我有一个Perl脚本,它分析一个文本文件(可以是UNIX或windows的行尾),当它找到感兴趣的内容时,存储文件偏移量 open(my $fh, $filename); my $groups; my %hash; while(<$fh>) { if($_ =~ /interesting/ ) { $hash{$groups++}{offset} = tell($fh); } } close $fh; 打开(我的$fh,$filename); 我的$组; 我
open(my $fh, $filename);
my $groups;
my %hash;
while(<$fh>) {
if($_ =~ /interesting/ ) {
$hash{$groups++}{offset} = tell($fh);
}
}
close $fh;
打开(我的$fh,$filename);
我的$组;
我的%hash;
while(){
如果($\=~/interest/){
$hash{$groups++}{offset}=tell($fh);
}
}
收盘价$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;
}
foreach my$组(关键字%hash){
my$href=$hash{$group};
我的$offset=$href->{offset};
我的$top;
打开($fh,$file);
读取($fh,$top,$offset);
my$bottom=do{local$/;};
收盘价$fh;
$href->{modified}=$top.“Hello World\n”。$bottom;
}
问题是read命令读取的字节太多。我怀疑这是一个行尾问题,因为输出的字节数(chars?)与行号相同。使用记事本++时,tell()
命令将返回到感兴趣点的实际偏移量,但在read()
中使用该偏移量值将返回超过感兴趣点的字符
open(my $fh, $filename);
my $groups;
my %hash;
while(<$fh>) {
if($_ =~ /interesting/ ) {
$hash{$groups++}{offset} = tell($fh);
}
}
close $fh;
我尝试在open()
命令之后,在read()之前添加binmode($fh)
。这确实在文本文件中找到了正确的位置,但随后我得到了(CR+CRLF)输出,文本文件中充满了双回车
我玩过layers:crlf,:bytes,但没有改进
有点卡住了
- 具有连续整数范围作为键的哈希应该是数组
- 每次出现
/interest/
- 听起来你需要做的就是
open(my $fh, $filename);
while (<$fh>) {
print;
print "Hello World\n" if /interesting/;
}
打开(我的$fh,$filename);
而(){
印刷品;
如果/interest/,则打印“Hello World\n”;
}
从
perldoc-f读取:
read FILEHANDLE,SCALAR,LENGTH,OFFSET
read FILEHANDLE,SCALAR,LENGTH
因此,当您这样做时:
read( $fh, $top, $offset);
您的$offset
实际上是一个长度。决定你需要读多少个字符<代码>读取
不考虑行尾,它读取指定的字节数
如果要读取一行,则不要使用read
,请使用:
seek($fh, $offset, 0);
$top = <$fh>;
seek($fh,$offset,0);
$top=;
您的文件中是否充满了两行新行,或者您添加了一行带有print
语句的新行 当输入文件不是ginormous时,我处理这个问题的标准方法是将文件插入并规范化行尾,将每一行存储为一个数组元素。有时我不得不在同一批文件中处理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;
}
你为什么不seek
定位,只打开一次文件?CRLF
不是字符。Windows文本文件的行以两个字符CR
和LF
或回车和换行符结尾。很难相信您的文件“充满了双回车符”。这就是我添加binmode()时得到的结果。作为字节字符串:/*********************************************************************************/CRCRLF/*链接器脚本*/CRCRLF@Borodin事实上,这很容易让人相信。crlf正是当您使用:crlf
层将“\r\n”
打印到文件句柄时得到的。Perl按原样打印CR,然后将LF转换为CRLF。@cjm:可能吧,但代码中没有任何CRs打印的迹象。Chris,除了在一行末尾打印“\n”
之外,你还打印其他内容吗?我已经尝试过简化我的示例,以避免混淆。是的,我需要生成一份完整文件的副本,其中附加了/interest/sections。文本文件实际上是一个链接器脚本,/interest/部分是.input部分。最后,Perl脚本将使用这些修改的链接器脚本中的每一个进行多线程调用LD。。我的问题是read()命令返回的字节太多。我本以为这是的作业,但只使用binmode$fh
应该没有问题。是的,您将在行尾获得LF
或CR
+LF
,具体取决于文件的来源,但是seek
中的值是正确的。