Powershell正则表达式从日志文件中提取数据

时间:2016-08-19 15:11:49

标签: regex powershell

处理脚本以从日志文件中提取数据;搜索查询和执行时间中的术语。

日志文件中的样本

19/08/2016 09:08:00 [100] ACTION%3DQuery%26MaxResults%3D9999%26abridged%3Dtrue%26abridgedmeta%3Ddatabase%26printfields%3DIM_DOCNUM,IM_VERSION%26combine%3Dfieldcheck%26databasematch%3DDATABASE_1,DATABASE-2%26Text%3D((pep21556)%3AIM_DOCNAME)%26fieldtext%3D(WILD%7BWORK%7D%3AIM_PRJ_SUBTYPE+AND+WILD%7BWEBDOC%7D%3AIM_CLASS)+AND+BIASDATE%7B1471612079e,2592000,20%7D%3Aautn_date+AND+BIASDATE%7B1471612079e,63072000,20%7D%3Aautn_date%26anyLanguage%3Dtrue%26TimeoutMS%3D60000
19/08/2016 09:08:00 [100] Request completed in 12 ms.
19/08/2016 09:08:28 [103] Request from 10.1.1.131

日志文件是URL编码的。

我的工作进度脚本加载日志文件

foreach ($line in [System.IO.File]::ReadLines($filename)) 

然后URLdecods每一行并删除一个长的securityinfo字符串

$VarURLDecoded = [System.Web.HttpUtility]::UrlDecode($line) -replace "SecurityInfo=.*"

现在我正在努力与RegEx提取以下内容:日期+时间,MaxResault = xxxxxxx,文字=((??????????):???????)和时间以ms为单位,请求在以下行中完成。

$findText = $VarURLDecoded | select-string -Inputobject {$_} -pattern 

我有一些部分正则表达式。

'(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2})'  will find 19/08/2016 09:08:00
'MaxResults=(\d*)' will find MaxResults=9999
'(?<Text>&Text=\(\([^()]*\)\:[^()]*\))' will find &Text=((campeau):IM_DOCNAME)
'(\d* ms)' will find the xx ms

但无法弄清楚加入它们的AND语法,包括第二行的持续时间记录。要么使用它遵循下面的线的事实,要么使用它具有适当时间戳的事实。

一旦我获得了基本的正则表达式,我就可以通过添加命名组并将结果导出到哈希表来增加复杂性。

1 个答案:

答案 0 :(得分:2)

根据发布的日志判断,由于没有%xx个编码字符,因此无需对其进行解码。
对于文本处理,不需要像[System.IO.File]这样的低级别的东西 需要额外的一行,所以让我们使用-context before, after参数。

$report = select-string -path $filename -context 0,1 -pattern (
    '^(?<date>.+?) ' +
    '(?<time>.+?) .+?' +
    '&MaxResults=(?<results>\d+).+?' +
    '&Text=(?<text>[^&]+)') |
%{
    $nextLine = $_.Context.PostContext[0]
    $g = $_.matches[0].groups
    @{
        date = $g['date'].value
        time = $g['time'].value
        results = $g['results'].value
        text = $g['text'].value
        duration = if ($nextLine -match 'completed in (\d+) ms') { $matches[1] }
    }
}

$report现在是一个对象数组,每个对象如下:

Name                           Value
----                           -----
date                           19/08/2016
time                           09:08:00
duration                       12
results                        9999
text                           ((pep21556):IM_DOCNAME)

或者,考虑到select-string的模式匹配可能会因复杂模式而变慢,让我们使用简单字符串进行匹配,使用?Where-Object的别名)进行过滤,然后处理结果:

$report = select-string -path $filename -context 0,1 -pattern '&MaxResults=' -simpleMatch |
?{ $_.Line -match (
    '^(?<date>.+?) ' +
    '(?<time>.+?) .+?' +
    '&MaxResults=(?<results>\d+).+?' +
    '&Text=(?<text>[^&]+)')
} | %{
    $nextLine = $_.Context.PostContext[0]
    $m = $matches # $matches is set by the above -match
    @{
        date = $m['date']
        time = $m['time']
        results = $m['results']
        text = $m['text']
        duration = if ($nextLine -match 'completed in (\d+) ms') { $matches[1] }
    }
}