在Perl中,如何过滤目录中的所有日志文件,并提取有趣的行?

EA0*_*A00 2 perl grep

我正在尝试仅选择目录中的.log文件,然后在这些文件中搜索单词"unbound",并将整行打印到一个新的输出文件中,其名称与日志文件(number###.log)相同但带有.txt扩展名.这是我到目前为止:

#!/usr/bin/perl

  use strict;
  use warnings;

  my $path = $ARGV[0];
  my $outpath = $ARGV[1];
  my @files;
  my $files;

  opendir(DIR,$path) or die "$!";
  @files = grep { /\.log$/} readdir(DIR);


  my @out;
  my $out;
  opendir(OUT,$outpath) or die "$!";

  my $line;
  foreach $files (@files) {
  open (FILE, "$files");
  my @line = <FILE>;
  my $regex = Unbound;
  open (OUT, ">>$out");
  print grep {$line =~ /$regex/ } <>;
   } 
  close OUT;
  close FILE;

  closedir(DIR);
  closedir (OUT);
Run Code Online (Sandbox Code Playgroud)

我是初学者,我真的不知道如何使用获得的输出创建新的文本文件.

Sob*_*que 6

我建议改进此代码的几件事情:

  • 在循环中声明循环迭代器. foreach my $file ( @files ) {
  • 使用3 arg open:open ( my $input_fh, "<", $filename );
  • 使用glob而不是opendir那么grep.foreach my $file ( <$path/*.txt> ) {
  • grep适合将事物提取到数组中.您grep读取整个文件进行打印,这是不必要的.如果文件很短,则无关紧要.
  • perltidy 非常适合重新格式化代码.
  • 你打开"OUT"到一个目录路径(我想?)这是行不通的.
  • $outpath不是,这是一个档案.您需要执行不同的操作才能输出到不同的文件.opendir对输出不是真的有效.
  • 因为你正在使用opendir它实际上给你的文件名 - 而不是完整的路径.所以你可能在错误的地方实际打开文件.预先设置路径名称,做一个chdir可能的解决方案.但这是我喜欢的原因之一,glob因为它也返回了一条路径.

所以考虑到这一点 - 如何:

#!/usr/bin/perl

use strict;
use warnings;
use File::Basename;

#Extract paths
my $input_path  = $ARGV[0];
my $output_path = $ARGV[1];

#Error if paths are invalid. 
unless (defined $input_path
    and -d $input_path
    and defined $output_path
    and -d $output_path )
{
    die "Usage: $0 <input_path> <output_path>\n";
}

foreach my $filename (<$input_path/*.log>) {

   # extract the 'name' bit of the filename. 
   # be slightly careful with this - it's based 
   # on an assumption which isn't always true. 
   # File::Spec is a more powerful way of accomplishing this.
   # but should grab 'number####' from /path/to/file/number####.log
   my $output_file = basename ( $filename, '.log' );

   #open input and output filehandles. 
   open( my $input_fh, "<", $filename ) or die $!;
   open( my $output_fh, ">", "$output_path/$output_file.txt" ) or die $!;

   print "Processing $filename -> $output_path/$output_file.txt\n";

   #iterate input, extracting into $line
   while ( my $line = <$input_fh> ) {
        #check if $line matches your RE. 
        if ( $line =~ m/Unbound/ ) {
            #write it to output. 
            print {$output_fh} $line;
        }
   }
   #tidy up our filehandles. Although technically, they'll 
   #close automatically because they leave scope
   close($output_fh);
   close($input_fh);
}
Run Code Online (Sandbox Code Playgroud)

  • 更新为使用`File :: Basename`作为一个不太好的例子:) (3认同)