我想读一个文件来提取几行信息。我创建了一个do ..直到忽略文件行,直到我到达我真正感兴趣的部分,其中包含单词V2000。我更喜欢使用一般的正则表达式,而不是寻找V2000。
匹配被找到,但它没有突破do .. until循环,因此我无法提取之后的信息
有谁知道为什么?
do {$line = <IN_SDF>;} until ($line =~ m/V\d+/);
其余代码是:
my @aline = split ('', $line);
my $natoms = $aline[0];
my $out= shift;
do{
<IN_SDF>;
@aline = split ('', $_);
print OUT_3D $aline[3]."\t".$aline[0]."\t".$aline[1]."\t".$aline[2]."\n";
} until --$natoms == 0;
答案 0 :(得分:13)
你是否假设裸露
<IN_SDF>
会将该文件句柄中的下一行加载到$_
吗?那是不对的。您只能使用while
表达式获得该行为:
while (<IN_SDF>) is equivalent to while (defined($_=<IN_SDF>))
如果你的意思是
$_ = <IN_SDF>
然后说出来。
对于你问题的第一部分,这个成语:
while ($line = <IN_SDF>) {
last if $line =~ m/V\d+/;
}
优于
do {
$line = <IN_SDF>
} until $line =~ m/V\d+/;
因为后一个表达式在输入用完时将进入无限循环($line
变为未定义)。
答案 1 :(得分:0)
让我直截了当。
'V'
,后面跟着行中的任意数字。 $natoms
,这是一个数字,告诉您要扫描多少行。这是对的吗?
至于你突破循环问题,当我运行该代码的版本时,它对我来说很好。严格或不严格。
答案 2 :(得分:0)
我试图解析破碎的单行50MB XML文件时遇到了这个问题。虽然我不知道它是否适用于原始海报,但我写了自己的子文件来做到这一点:
sub ReadNext($$) {
my ($hh, $pattern) = @_;
my ($buffer, $chunk, $chunkSize) = ('', '', 512);
while(my $bytesRead = read($hh, $chunk, $chunkSize) > 0) {
$buffer .= $chunk;
if ($buffer =~ $pattern) {
my ($matchStart, $matchEnd) = (@-, @+);
my $result = substr($buffer, $matchStart, $matchEnd - $matchStart);
my $pos = tell($hh);
# Rewind the stream to where this match left off
seek($hh, ($pos -= length($buffer)-$matchEnd), 0);
return $result;
}
}
undef;
}
open(my $fh, $ARGV[0]) or die("Could not open file: $!");
while(my $chunk = ReadNext($fh, qr/<RECORD>.+?<\/RECORD>/)) {
print $chunk, "\n";
}
close($fh);
对我来说,使用换行符从XML打印出每个RECORD元素。