Perl - 在找到正则表达式之前执行{read file}。查找匹配但不会突破循环

时间:2011-09-21 15:44:36

标签: regex perl

我想读一个文件来提取几行信息。我创建了一个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;

3 个答案:

答案 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)

让我直截了当。

  1. 您希望扫描输入,直到您看到一行'V',后面跟着行中的任意数字。
  2. 然后你想按字符划分界限
  3. 并将该行中的第一个字符指定给$natoms,这是一个数字,告诉您要扫描多少行。
  4. 然后你要扫描每一行并显示前4个字符。
  5. 这是对的吗?

    至于你突破循环问题,当我运行该代码的版本时,它对我来说很好。严格或不严格。

答案 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元素。