【问题标题】:Recursive grep in perlperl中的递归grep
【发布时间】:2016-02-18 09:00:30
【问题描述】:

我是 perl 的新手。我有一个目录结构。在每个目录中,我都有一个日志文件。我想从该文件中提取模式并进行后期处理。现在我正在使用 unix grep 从这些文件中提取模式并将其放入文本文件并读取该文本文件以进行后处理,但我想自动执行读取每个文件并从该文件中提取模式的任务。在下面的代码中,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]";
}

【问题讨论】:

  • 你能展示一个示例目录结构和一个你想要grep的字符串的例子吗?
  • 可能是File::Find 的工作。如果没有更多信息,很难说你在做什么。
  • 所以文本文件有 unix grep 的输出,你想使用那个输出吗?
  • 需要一些输出文本文件的样本。
  • 您是否需要自动化构建文件列表的过程,正如帖子标题所暗示的那样,或者扫描(已知)文件以查找模式的过程,正如您在帖子中具体所说的那样?还是……两者都有?

标签: perl recursion grep file-handling


【解决方案1】:

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

一种方法:从每个文件中提取所有模式并将其存储在哈希中(文件名 => 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 返回的列表,即。构造一个“匿名数组”,并将其(引用)作为值分配给$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::Find::name,您可以在其中使用patterns-per-log 填充哈希,如上所示,或根据需要运行完整的处理。

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

另一种方法是使用另一个调用

find(\&process_all, @dir_list);

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

【讨论】:

    【解决方案2】:

    相当于

    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;
    

    【讨论】:

      【解决方案3】:

      使用File::Find遍历目录。

      循环遍历所有日志文件:

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

      我希望这可以为您提供足够的入门指导。如果您自己了解如何在 Perl 中完成这些步骤,您将了解更多信息(我指出了困难的步骤)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-16
        • 1970-01-01
        • 2010-11-10
        • 2010-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多