Powershell:从日志文件中提取数据以创建新对象

时间:2016-08-18 15:38:57

标签: powershell

我和PowerShell一起磕磕绊绊。

我有脚本在数百台PC上解析相同的日志文件,提取我们感兴趣的两种类型的交易。

此行执行模式匹配,将每行日志保存在一个包含多行的变量中。我将匹配对象转换为字符串,以便稍后将其拆分。

$strLogEvents = select-string -path \\$Cmpname\c$\ProgramData\IS\Logs\DMS\outlook.* -pattern '(doFolderDocSearch ends, duration)|(doDocSearch ends, duration)' | ForEach-Object {$_.ToString()}

这是$ StrLogEvents为单个PC保存的内容

\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log:325:Wed 08/17 10:24:44.983 PerformanceContext:  59:Info2 [10728] System call doDocSearch ends, duration 60203 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:886:Fri 08/05 16:23:14.249 PerformanceContext:  59:Info2 [12204] System call DoFolderDocSearch ends, duration 1796 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:963:Fri 08/05 16:23:27.901 PerformanceContext:  59:Info2 [12204] System call DoFolderDocSearch ends, duration 250 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:1046:Fri 08/05 16:23:41.625 PerformanceContext:  59:Info2 [12204] System call doDocSearch ends, duration 171 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:1422:Sun 08/07 23:08:49.107 PerformanceContext:  59:Info2 [12204] System call DoFolderDocSearch ends, duration 250 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:1786:Sun 08/07 23:09:42.750 PerformanceContext:  59:Info2 [12204] System call doDocSearch ends, duration 407 ms
\\naimc\c$\ProgramData\IS\Logs\DMS\OUTLOOK.log_bak:1847:Sun 08/07 23:10:05.494 PerformanceContext:  59:Info2 [12204] System call doDocSearch ends, duration 454 ms

对于每一行,我只对重新训练计算机名,日期,时间,系统调用类型,持续时间(以毫秒为单位)感兴趣。

我可以用这个进一步分解字符串数组:

$ParsedLogEvents = $strLogEvents | ForEach-Object {$_.split("\, ",[System.StringSplitOptions]::RemoveEmptyEntries)}

$ ParsedLogEvents中的字符串现在包含每个" piece"的一条简洁行。数据

示例:每个项目都在其自己的行上。我添加了***来表示我想要保留的行。

naimc***-PCName
c$
ProgramData
IS
Logs
DMS
OUTLOOK.log_bak:4602:Mon
08/15*** -Date
14:36:01.667 -Time
PerformanceContext:
59:Info2
[10928]
System
call
doDocSearch ***-EventType
ends
duration
47 ***-Duration
ms
naimc
c$
ProgramData
Osler
IS
Logs
DMS
OUTLOOK.log_bak:4610:Mon
08/15 
14:36:01.748 
PerformanceContext:
59:Info2
[10928]
System
call
doDocSearch 
ends
duration
31 
ms

我认为我必须将每一行作为单个变量处理。 (不能弄清楚这个简单的部分是怎么做的)。在我可以简单地使用$ ParsedLogEvents [lineNumber]返回我想要保留的行的记录以创建哈希表或对象。这将允许我保存为CSV或导出到SQL数据库。我现在无法做到这一点,因为每一行所有原始事件都在这一大阵列中。

有什么建议吗?我是朝着正确的方向前进的吗?

2 个答案:

答案 0 :(得分:3)

通过正则表达式模式的命名组在Select-String中进行字段解析:

$report = select-string `
    -path \\$Cmpname\c$\ProgramData\IS\Logs\DMS\outlook.* `
    -pattern ('(?<date>.+? .+?) ' +
        '(?<time>.+?) .+? ' +
        '(?<syscall>doFolderDocSearch|doDocSearch) ends, duration ' +
        '(?<duration>.+?) ms') `
| %{
    $g = $_.matches[0].groups
    @{
        computer = $Cmpname
        date = $g['date'].value
        time = $g['time'].value
        syscall = $g['syscall'].value
        duration = $g['duration'].value
    }
}

将生成一个可以$report[1].computer$report[1].date访问的对象数组,依此类推:

Name                           Value
----                           -----
date                           Wed 08/17
time                           10:24:44.983
syscall                        doDocSearch
computer                       naimc
duration                       60203

答案 1 :(得分:0)

非常好!这是我看到的正则表达式命名组的第一个例子

由于某种原因,您的原始样本没有返回任何结果,它运行了几分钟但没有捕获任何内容。我不得不在小部分打破你的例子来理解这个概念

我保留了我的基本行进行初始解析,将其保留为matchinfo格式。

$strLogEvents = select-string -path \\$Cmpname\c$\ProgramData\IS\Logs\DMS\outlook.* -pattern '(doFolderDocSearch ends, duration)|(doDocSearch ends, duration)' 

他们在第二个选择字符串中传递了Matchinfo.Line,它使您的代码文本有效且速度很快。

$report = $strLogEvents | select-string -Inputobject {$_.line} -pattern ('(?<date>.+? .+?) ' + '(?<time>.+?) .+? ' + '(?<syscall>doFolderDocSearch|doDocSearch) ends, duration ' + '(?<duration>.+?) ms') | %{
    $g = $_.matches[0].groups
    @{
        computer = $Cmpname
        date = $g['date'].value
        time = $g['time'].value
        syscall = $g['syscall'].value
        duration = $g['duration'].value
    }
}