我和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数据库。我现在无法做到这一点,因为每一行所有原始事件都在这一大阵列中。
有什么建议吗?我是朝着正确的方向前进的吗?
答案 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
}
}