Perl Regex:使用多行文档否定前瞻?

时间:2015-10-02 16:08:41

标签: regex perl

我正在尝试解析一些Microsoft日志记录信息。这些日志来自于所谓的“人类可读”文本的大块,其中的例子可以在Windows Security Blog看到,并且有一个特定的事件我想从我的分析中排除,即“一个操作是在一个对象“当有问题的对象是groupPolicyContainer时。

这是我的正则表达式和测试代码:

my $re = qr/(?ms)EventCode=(4662)[^\d].*Object Type:\s*((?!groupPolicyContainer)\S)*/;
if ($sample1 =~ $re) { print "Matches -- should not have\n"; }
if ($sample2 =~ $re) { print "Matches -- and should have!\n"; }

$sample1包含短语Object Type: groupPolicyContainer$sample2包含短语Object Type: Key。 (它们都具有相同的EventCode;这是一个人为的测试用例。)如果查看链接,可以看到围绕两个关键短语“EventCode”和“Object Type”的文本很多。 “对象类型”每个日志条目不会出现多次(在我设计的测试用例中)。

正则表达式说:两者都匹配。我的期望是第一个不应该匹配,因为它包含否定的短语!我试图实现previous Stack Overflow response中显示的代码,但它似乎没有工作;这个例子和我的唯一区别是我的操作是一个多行文件。

我已经尝试过(?ms)我想到的所有可能的组合!我需要做些什么才能在多行文档中使用它?

1 个答案:

答案 0 :(得分:1)

就个人而言 - 我认为你对单一的正则表达式方法有点过分了解。我建议改为 - 将对象解析为散列,然后测试散列的相关键。

正则表达式的问题在于它努力匹配。如果失败,则返回跟踪并寻找其他潜在的匹配点。所以在多行中,可能会跳到下一条记录,寻找匹配的块,特别是如果你有多行贪心匹配。

你可以看到

发生了什么
use re 'debug';

这将向您展示正则表达式引擎正在做什么。

但一般来说,我会建议,鉴于你有perl,试图制作胜利的正则表达是不必要的痛苦。

我知道这不是你提出的要求,但希望这能说明我的意思

#!/usr/bin/env perl 
use strict;
use warnings;

use Data::Dumper;

local $/; #set this to your record separator, and you can
          #use this with a while loop too!
my %this_object = <DATA> =~ m/^\s*(.*): (.*)$/gm;
print Dumper \%this_object;

if (    $this_object{'Handle ID'} eq '0x178'
    and $this_object{'Object Type'} eq 'File' )
{
    print "Matches this criteria\n";
}

__DATA__
Subject:
  Security ID: LB\administrator
  Account Name: administrator
  Account Domain: LB
  Logon ID: 0x3DE02

Object:
  Object Server: Security
  Object Type: File
  Object Name: C:\asdf\New Text Document.txt
  Handle ID: 0x178
  Resource Attributes: S:AI


Process Information:
  Process ID: 0x113c
  Process Name: C:\Windows\System32\notepad.exe

Access Request Information:
  Accesses: WriteData (or AddFile)
    AppendData (or AddSubdirectory or CreatePipeInstance)
    Access Mask: 0x6

打印:

$VAR1 = {
          'Logon ID' => '0x3DE02',
          'Process ID' => '0x113c',
          'Process Name' => 'C:\\Windows\\System32\\notepad.exe',
          'Resource Attributes' => 'S:AI',
          'Account Domain' => 'LB',
          'Accesses' => 'WriteData (or AddFile)',
          'Security ID' => 'LB\\administrator',
          'Access Mask' => '0x6',
          'Object Type' => 'File',
          'Object Name' => 'C:\\asdf\\New Text Document.txt',
          'Object Server' => 'Security',
          'Account Name' => 'administrator',
          'Handle ID' => '0x178'
        };
Matches this criteria

但是,如果这太“过分”,那么这又怎么样呢?:

if (    $thing =~ m/EventCode: 4666/
    and not $thing =~ m/groupPolicyContainer/ ) {
    print "Matches this criteria\n";
}

保存必须找出负正则表达式匹配,并且可能也更有效,因为它不需要回溯。