【问题标题】:How to count the number of matches in a regex capture group - Perl如何计算正则表达式捕获组中的匹配数 - Perl
【发布时间】:2019-05-06 21:51:39
【问题描述】:

我需要一种方法来使用 Perl 或 Bash 计算正则表达式捕获组中的匹配数。我可以在 Powershell 中执行此操作,但不能使用这两种语言中的任何一种。你们帮助我让我的正则表达式工作,但我看到的每个例子都只是打印捕获组。打印匹配结果对我没有帮助,我需要计算每组的匹配数。

这是正则表达式的示例数据(这是命令的输出,因此不是静态数据,也不是来自文件)

   JobID           Type State Status               Policy Schedule     Client Dest Media Svr Active PID
   41735         Backup  Done      0     Policy_name_here    daily hostname001 MediaSvr1       8100
   41734         Backup  Done      0     Policy_name_here    daily hostname002 MediaSvr1       7803
   41733         Backup  Done      0     Policy_name_here    daily hostname004 MediaSvr1       7785
   41732         Backup  Done      0     Policy_name_here    daily hostname005 MediaSvr1       27697
   41731         Backup  Done      0     Folicy_name_here    daily hostname006 MediaSvr1       27523
   41730         Backup  Done      0     Policy_name_here    daily hostname007 MediaSvr1       27834
   41729         Backup  Done      0     Policy_name_here        - hostname008 MediaSvr1       27681
   41728         Backup  Done      0     Policy_name_here        - hostname009 MediaSvr1       27496
   41727 Catalog Backup  Done      0              catalog     full hostname010 MediaSvr1       27347
   41712 Catalog Backup  Done      0              catalog        - hostname004                 30564 

我不能像使用 Perl 5.8.5 一样使用命名捕获组

我的正则表达式

/(\d+)?\s+((\b[^\d\W]+\b)|(\b[^\d\W]+\b\s+\b[^\d\W]+\b))?\s+((Done)|(Active)|(\w+\w+\-\w\-+))?\s+(\d+)?\s+((\w+)|(\w+\_\w+)|(\w+\_\w+\_\w+))?\s+((b[^\d\W]+\b\-\b[^\d\W]+\b)|(\-)|(\b[^\d\W]+\b))?\s+((\w+\.\w+\.\w+)|(\w+))?\s+((\w+\.\w+\.\w+)|(\w+))?\s+(\d+)?/g

每个捕获组对应一个列,我需要将捕获组的结果拉到一个变量中,所以我可以使用某种where {$var -eq '0'}.count 代码进行计数。假设Status -eq '0'表示备份成功,我需要统计Status捕获组中成功备份的次数。

最终输出类似于

Statistic.SUCCESSFUL: 20

我已经使用 Powershell 完成了这项工作,但 Perl 完全不同,而且 Bash 似乎有限。如果有人知道如何用这两种语言中的任何一种完成上述操作,我将不胜感激。

亲切的问候,

DJ

【问题讨论】:

  • 你要my @captures = $string =~ /.../;吗?
  • 我假设这会将我所有的匹配项放入一个数组中。例如,我可以计算捕获组 1 $1 中的匹配数吗?如果是这样,我该如何做到这一点?
  • 嗯? $1 的字符串中正好有一个。
  • 我看到你使用了/g。不要那样做。匹配每一行。
  • 我只是想知道如何计算捕获组中的匹配数...$1 是一个捕获组,其中包含“JobID”列的内容。

标签: regex bash perl capture-group


【解决方案1】:
<>;  # Skip header

my $successes = 0;
while (<>) {
   chomp;
   my @row = /.../
      or do {
         die("Line $. doesn't match pattern\n");
         next;
      };

   ++$successes if $row[3] eq '0';
}

您也可以命名列。

<>;  # Skip header

my $successes = 0;
while (<>) {
   chomp;
   my %row;
   @row{qw( JobID Type State Status ... )}  = /.../
      or do {
         die("Line $. doesn't match pattern\n");
         next;
      };

   ++$successes if $row{Status} eq '0';
}

最后,如果您想将数据存储在数据结构中以供以后分析,这也是可能的。

<>;  # Skip header

my @rows;
while (<>) {
   chomp;
   my %row;
   @row{qw( JobID Type State Status ... )}  = /.../
      or do {
         die("Line $. doesn't match pattern\n");
         next;
      };

   push @rows, \%row;
}

my $successes = grep { $_->{Status} eq '0' } @rows;

最后,这个正则表达式模式……糟糕透了。我会选择这样的:

sub trim(_) { $_[0] =~ s/^\s++|\s++\z//rg }

my $pattern;
my @headers;
{
   my $header_line = <>;
   chomp($header_line);
   $header_line =~ s/\bDest Media Svr\b/Dest_Media_Svr/;
   $header_line =~ s/\bActive PID\b/Active_PID/;
   $pattern = join '', map { "A".length($_) } $header_line =~ /\s*\S+/g;
   @headers = map trim, unpack $pattern, $header_line;
}

my @rows;
while (<>) {
   chomp;
   my %row; @row{@headers} = map trim, unpack $pattern, $_;
   push @rows, \%row;
}

my $successes = grep { $_->{Status} eq '0' } @rows;

【讨论】:

    猜你喜欢
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多