从文件中提取正则表达式并与文件中的每一行进行比较

时间:2013-01-10 21:08:06

标签: regex perl eval runtime-error

我发现了一些我可以在perlmonks.org上使用的东西(http://www.perlmonks.org/?node_id=870806),但我无法让它工作。

我可以毫无问题地阅读该文件并构建一个数组。然后,我想将数组的每个索引(每个正则表达式)与文件的每一行进行比较,打印出匹配行之前的行和行之后的行。

我的代码:

# List of regex's.  If this file doesn't exist, we can't continue
open ( $fh, "<", $DEF_FILE ) || die ("Can't open regex file: $DEF_FILE");
while (<$fh>) {
    chomp;
    push (@bad_strings, $_);
}
close $fh || die "Cannot close regex file: $DEF_FILE: $!";

$file = '/tmp/mydirectory/myfile.txt';
eval { open ( $fh, "<", $file ); };
if ($@) {
      # If there was an error opening the file, just move on
      print "Error opening file: $file.\n";
} else {
      # If no error, process the file
      foreach $bad_string (@bad_strings) {
              $this_line = "";
              $do_next = 0;
              seek($fh, 0, 0); # move pointer to 0 each time through
              while(<$fh>) {
                      $last_line = $this_line;
                      $this_line = $_;
                      my $rege = eval "sub{ \$_[0] =~ $bad_string }"; # Real-time regex
                      if ($rege->( $this_line )) {                    # Line 82
                             print $last_line unless $do_next;
                             print $this_line;
                             $do_next = 1;
                      } else {
                             print $this_line if $do_next;
                             $last_line = "";
                             $do_next = 0;
                      }
              }
      }
}  # End "if error opening file" check

之前我在文件中每行只有一个字符串并执行了一个简单的测试,例如if ($this_line =~ /$string_to_search_for/i ),但当我在文件中切换到正则表达式并执行“实时”eval语句时现在获得Can't use string ("") as a subroutine ref while "strict refs" in use at scrub_file.pl line 82,第82行是if ($rege->($this_line)) {

在出现该错误消息之前,我收到了:Use of uninitialized value in subroutine entry at scrub_hhsysdump_file.pl line 82, <$fh>我对该错误消息有所了解,但似乎无法使perl引擎对我的代码感到满意。

仍然是perl的新手并且总是在寻找指针。提前谢谢。

1 个答案:

答案 0 :(得分:2)

我没有看到这些eval语句的原因 - 他们似乎只是使代码变得更加复杂和难以调试。

但是$rege是undef,因为eval "sub{ \$_[0] =~ $bad_string }"不起作用,因为字符串有语法错误。我不知道$DEF_FILE中有什么,但除非它有正确分隔的正则表达式,否则你需要在eval字符串中添加分隔符。

my $rege = eval "sub{ \$_[0] =~ /$bad_string/ }"

可能有效,但如果/\Q$bad_string/中的字符串包含正则表达式元字符,并且您希望将它们视为文字字符,则可能需要$DEF_FILE

我建议您使用此版本的程序,而不必担心eval来电。

use strict;
use warnings;

use Fcntl ':seek';

my $DEF_FILE = 'myfile';

my @bad_strings = do {
  open my $fh, '<', $DEF_FILE or die qq(Can't open regex file "$DEF_FILE": $!);
  <$fh>;
};
chomp @bad_strings;

my $file = '/tmp/mydirectory/myfile.txt';

open my $fh, '<', $file or die qq(Unable to open "$file" for input: $!);

for my $bad_string (@bad_strings) {

  my $regex = qr/$bad_string/;

  my ($last_line, $this_line, $do_next) = ('', '', 0);

  seek $fh, 0, SEEK_SET;

  while (<$fh>) {

    ($last_line, $this_line) = ($this_line, $_);

    if ($this_line =~ $regex) {
      print $last_line unless $do_next;
      print $this_line;
      $do_next = 1;
    }
    else {
      print $this_line if $do_next;
      $do_next = 0;
    }
  }
}