perl中的递归grep

Recursive grep in perl

我是 perl 新手。我有一个目录结构。在每个目录中,我都有一个日志文件。我想从该文件中获取模式并进行 post 处理。现在我正在使用 unix grep 从这些文件中获取模式并将其放入文本文件并读取该文本文件以进行 post 处理,但我想自动执行读取每个文件并从该文件中获取模式的任务。在下面的代码中,mdp_cgdis_1102.txt 从目录中获取了模式。我真的很感激任何帮助

#!usr/bin/perl

use strict;
use warnings;

open FILE, 'mdp_cgdis_1102.txt' or die "Cannot open file $!";

my @array = <FILE>;
my @arr;
my @brr;

foreach my  $i (@array){
@arr = split (/\//, $i);
@brr = split (/\:/, $i);
print " $arr[0] ---  $brr[2]";
}

使用File::Find遍历目录。

循环遍历所有日志文件:

  1. 打开文件
  2. 逐行阅读
  3. 对于每一行,做一个正则表达式匹配( if ($line =~ /pattern/) ) 或使用 if (index($line, $searchterm) >= 0) 如果您正在寻找某个静态字符串。
  4. 如果找到匹配项,打印该行。
  5. 关闭文件

我希望这能为您提供足够的入门指南。如果您自己了解如何在 Perl 中执行这些步骤,您将会学到更多(我指出了困难的步骤)。

相当于

find ... -name '*.txt' -type f -exec grep ... {} +

use File::Find::Rule qw( );

my $base_dir_qfn = ...;
my $re = qr/.../;

my @log_qfns =
   File::Find::Rule
   ->name(qr/\..txt\z/)
   ->file
   ->in($base_dir_qfn);

my $success = 1;
for my $log_qfn (@log_qfns) {
   open(my $fh, '<', $log_qfn)
      or do {
         $success = 0;
         warn("Can't open log file \"$log_qfn\": $!\n);
         next;
      };

   while (<$fh>) {
      print if /$re/;
   }
}

exit(1) if !$success;

我不清楚流程的哪一部分需要自动化。我将通过“想要自动读取每个文件并从该文件中提取模式”,据推测您可能已经有了一个文件列表。如果您确实需要构建文件列表,请参阅下面添加的代码。

一种方法:从每个文件中提取所有模式并将其存储在哈希中(文件名 => arrayref-with-patterns)

my %file_pattern;
foreach my $file (@filelist) {
    open my $fh, '<', $file or die "Can't open $file: $!";
    $file_pattern{$file} = [ grep { /$pattern/ } <$fh> ];
    close $fh;
}

[ ] 引用了 grep 返回的列表,即。构造一个 "anonymous array",并将该(引用)作为值分配给 $file 键。

现在您可以根据日志文件处理您的模式

foreach my $filename (sort keys %file_pattern) {
    print "Processing log $filename.\n";
    my @patterns = @{$file_pattern{$filename}};
    # Process the list of patterns in this log file
}  


已添加

为了构建上面使用的文件列表 @filelist,从已知的目录列表中,使用核心 File::Find 递归扫描提供的目录并应用提供的子例程的模块

use File::Find;
find( { wanted => \&process_logs, preprocess => \&select_logs }, @dir_list);

你的子例程 process_logs() 被应用到每个 file/directory 通过第二个子程序的预处理,其名称可用 $File::Find::name,你可以在其中填充散列patterns-per-log 如上所示,或 运行 根据需要完成处理。

您的子例程 select_logs() 包含从每个目录中的所有文件中过滤日志文件的代码,File::Find 通常会处理这些文件,因此 process_file() 仅获取日志文件。

另一种方法是使用其他调用

find(\&process_all, @dir_list);

现在 sub process_all() 应用于找到的所有条目(文件和目录),因此该 sub 本身需要确保它只处理日志文件。请参阅链接文档。