查找多行块

时间:2014-10-31 07:13:59

标签: regex perl file-io

我试图从文件底部的文件test.out中找到BLOB_SMUGHO的出现位置。如果找到,请返回我感兴趣的字符串" 2014.10"

之间的一大块数据
  

我在模式匹配(m //)中使用未初始化的值$ cc

这个脚本有什么问题?

#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(strftime);
use File::ReadBackwards;

my $find = "BLOB_SMUGHO";
my $chnkdelim = "\n[" . strftime "%Y.%m", localtime;

my $fh = File::ReadBackwards->new('test.out', $chnkdelim, 0) or die "err-file: $!\n";

while ( defined(my $line = $fh->readline) ) {
     if(my $cc =~ /$find/){
        print $cc;
     }
}

close($fh);

如果这有帮助,这里是test.out

的示例内容
2014.10.31 lots and 
lots of 
gibbrish 
2014.10.31 which I'm not 
interested 
in. It 
also 
2014.10.31 spans
across thousands of 
lines and somewhere in the middle there will be
2014.10.31
this precious word BLOB_SMUGHO and 
2014.10.31 certain other 
2014.10.31 words 
2014.10.31
this precious word BLOB_SMUGHO and
2014.10.31
this precious word BLOB_SMUGHO and
which 
I 
will 
be 
interested 
in.

我希望从文件底部捕获文本块的所有多次出现。

2014.10.31
this precious word BLOB_SMUGHO and 

1 个答案:

答案 0 :(得分:2)

首先,由于误解=~运算符,您错误地写了您的匹配:

if(my $cc =~ /$find/){   # incorrect, like saying   if(undef matches something)

如果您想将$line中的内容与/.../之间的模式进行匹配,请执行以下操作:

if($line =~ /$find/) {

匹配运算符需要左侧和右侧的值。你像使用赋值运算符一样使用它。

如果您需要将匹配项捕获到变量或列表中,请将其添加到等号的左侧:

if(my ($cc) = $line =~ /$find/) {       <--  wrap $cc in () for list context

顺便说一句,我认为你写作会更好:

if($line =~ /$find/) {
    print $line;

或者如果您想打印仅匹配的内容

    print $0;

由于你没有捕获子字符串,所以在这里并不重要。

现在,关于如何匹配两个模式之间的所有内容,如果您不逐行匹配,但使用/ s修饰符匹配换行符,则任务会更容易。

在Perl中,您可以将记录分隔符设置为undef并使用slurp模式。

local $/ = undef;
my $s = <>;        # read all lines into $s

现在扫描$ s寻找模式

while($s =~ /(START.*?STOP)/gsm) {  print "$1\n"; }   # print the pattern inclusive of START and STOP

或者在START和STOP之间捕捉

while($s =~ /START(.*?)STOP/gsm) {  print "$1\n"; }   # print the pattern between of START and STOP

因此,在您的情况下,起始模式为2014.10.31,停止为BLOB_SMUGHO

while($s =~ /(2014\.10\.31.*?BLOB_SMUGHO)/gsm) {
    print "$1\n";
}

注意:Perl中的正则表达式修饰符位于最后一个/之后,因此如果您看到我使用/gsm进行多行,匹配换行和全局匹配(通过记住最后一个位置在循环中获取多个匹配项) )。