解析日志文件并将其转换为自定义对象
Parse log file and turn it into a custom object
日志文件包含:
=====
SMTP_server_not_set_up
@PANEL SMTP server not set up. Contact system administrator.
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:51-0400
@UPTIME 0:00:23
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
PowerOnReset
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:50-0400
@PORCNT 49
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
Load_MP_Feeder_with_Custom_Type_5_Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
@PAGECNT 337
@SCANADFCNT 0
@DATETIME 2019-08-29T09:59:22-0400
@UPTIME 0:44:15
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
...还有很多行
我想抓取“=====”行之后的 6 行并将其变成自定义对象。
例如,根据第一行,理想的对象是:
MESSAGE: SMTP_server_not_set_up
PANEL : @PANEL SMTP server not set up. Contact system administrator.
PAGECNT: @PAGECNT 381
SCANADFCNT :@SCANADFCNT 0
DATETIME : @DATETIME 2019-08-29T10:05:51-0400
UPTIME: @UPTIME 0:00:23
到目前为止,我可以像这样隔离重复出现的“=====”后面的 6 行:
(Select-String -Path "$PSScriptRoot$($printer)_history.log" -Pattern "=====" -Context 6).Context.PostContext
现在我需要将这些行放入自定义对象中。我真的不知道如何正确处理这个问题,我正在探索做这样的事情:
$ObjHistory = @()
(Select-String -Path "$PSScriptRoot$($printer)_history.log" -Pattern "=====" -Context 6).Context.PostContext | ForEach-Object {
if ($_ -match "PANEL") {
$properties = [ordered]@{'PANEL'="$_"}
$objet = New-Object -TypeName PSObject -Property $properties
}
$ObjHistory += $objet
}
$ObjHistory
这样我发现我可以成功地将 PANEL 属性 放入自定义对象中,它输出:
PANEL
-----
@PANEL SMTP server not set up. Contact system administrator.
@PANEL Load MP Feeder with Custom Type 5 Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
但是,我需要对其他行执行此操作,并且我一直不知道如何处理它,因为 ForEach-Object
一次处理一行。
提取的数据已经具有 key/value 种结构,因此您可以使用 ConvertFrom-StringData
将数据块转换为哈希表,然后转换为自定义对象。
避免在循环中附加到数组。只需输出循环中的对象,并将循环输出收集到一个变量中。
$path = "${PSScriptRoot}${printer}_history.log"
$objHistory = @(Select-String -Path $path -Pattern '=====' -Context 6 | ForEach-Object {
$props = $_.Context.PostContext -replace '^[^@]', 'MESSAGE = $&' -replace '^@(\w+)', ' = $&' |
Out-String |
ConvertFrom-StringData
New-Object -Type PSObject -Property $props
})
-replace '^[^@]', 'MESSAGE = $&'
在不以 @
开头的行前面加上字符串 MESSAGE =
,-replace '^@(\w+)', ' = $&'
替换 @WORD
开头的行符合 WORD = @WORD
。随后的 Out-String
然后将数据块合并为一个字符串,否则 ConvertFrom-StringData
将每行创建一个哈希表。
一种不同的方法
- 使用-raw参数读取登录
- 在
=====
处拆分成多个部分
- 将部分拆分为行并将这些行存储到变量中以输出为
[PSCustomObject]
编辑
- 创建一个空的
[PSCustomObject]
并使用正则表达式填充相关属性
(如果需要,清理多余的@propname)
## Q:\Test19\SO_57773555.ps1
$RE = [regex]'^@(MESSAGE|PANEL|PAGECNT|SCANADFCNT|DATETIME|UPTIME) +(.*)$'
$Path = "$PSScriptRoot$($printer)_history.log"
$ObjHistory = foreach($Section in ((Get-Content $Path -raw) -split '===== ?\r?\n' -ne '')){
$obj = [PSCustomobject]@{MESSAGE="";PANEL="";PAGECNT="";SCANADFCNT="";DATETIME="";UPTIME=""}
$obj.MESSAGE = ($Section -split '\r?\n')[0]
foreach($Line in ($Section -split '\r?\n')[1..5] ){
if($Line -match $RE){
$obj.($Matches[1])=$Matches[2] # to have the complete line =$Matches[0]
}
}
$obj
}
$ObjHistory
> .\SO_57773555.ps1
MESSAGE : SMTP_server_not_set_up
PANEL : SMTP server not set up. Contact system administrator.
PAGECNT : 381
SCANADFCNT : 0
DATETIME : 2019-08-29T10:05:51-0400
UPTIME : 0:00:23
MESSAGE : PowerOnReset
PANEL :
PAGECNT : 381
SCANADFCNT : 0
DATETIME : 2019-08-29T10:05:50-0400
UPTIME :
MESSAGE : Load_MP_Feeder_with_Custom_Type_5_Letter
PANEL : Load MP Feeder with Custom Type 5 Letter
PAGECNT : 337
SCANADFCNT : 0
DATETIME : 2019-08-29T09:59:22-0400
UPTIME : 0:44:15
尝试了 convertfrom-string,基于示例的解析。多个示例效果更好。
$template = @'
=====
{message*:SMTP_server_not_set_up}
{panel:@PANEL SMTP server not set up. Contact system administrator.}
{pagecnt:@PAGECNT 381}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T10:05:51-0400}
{uptime:@UPTIME 0:00:23}
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
{message*:PowerOnReset}
{pagecnt:@PAGECNT 381}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T10:05:50-0400}
@PORCNT 49
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
{message*:Load_MP_Feeder_with_Custom_Type_5_Letter}
{panel:@PANEL Load MP Feeder with Custom Type 5 Letter}
{pagecnt:@PAGECNT 337}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T09:59:22-0400}
{uptime:@UPTIME 0:44:15}
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
'@
$testtext = @'
=====
SMTP_server_not_set_up
@PANEL SMTP server not set up. Contact system administrator.
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:51-0400
@UPTIME 0:00:23
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
PowerOnReset
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:50-0400
@PORCNT 49
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
Load_MP_Feeder_with_Custom_Type_5_Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
@PAGECNT 337
@SCANADFCNT 0
@DATETIME 2019-08-29T09:59:22-0400
@UPTIME 0:44:15
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
'@
$testText | ConvertFrom-String -TemplateContent $template
输出:
message : SMTP_server_not_set_up
panel : @PANEL SMTP server not set up. Contact system administrator.
pagecnt : @PAGECNT 381
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T10:05:51-0400
uptime : @UPTIME 0:00:23
message : PowerOnReset
pagecnt : @PAGECNT 381
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T10:05:50-0400
message : Load_MP_Feeder_with_Custom_Type_5_Letter
panel : @PANEL Load MP Feeder with Custom Type 5 Letter
pagecnt : @PAGECNT 337
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T09:59:22-0400
uptime : @UPTIME 0:44:15
日志文件包含:
===== SMTP_server_not_set_up @PANEL SMTP server not set up. Contact system administrator. @PAGECNT 381 @SCANADFCNT 0 @DATETIME 2019-08-29T10:05:51-0400 @UPTIME 0:00:23 @CODELVL Base MSNGM.053.023 Engine GM.052.E015 Panel f0.12p48v3 @END ===== PowerOnReset @PAGECNT 381 @SCANADFCNT 0 @DATETIME 2019-08-29T10:05:50-0400 @PORCNT 49 @CODELVL Base MSNGM.053.023 Engine GM.052.E015 Panel f0.12p48v3 @END ===== Load_MP_Feeder_with_Custom_Type_5_Letter @PANEL Load MP Feeder with Custom Type 5 Letter @PAGECNT 337 @SCANADFCNT 0 @DATETIME 2019-08-29T09:59:22-0400 @UPTIME 0:44:15 @CODELVL Base MSNGM.053.023 Engine GM.052.E015 Panel f0.12p48v3 @END =====
...还有很多行
我想抓取“=====”行之后的 6 行并将其变成自定义对象。
例如,根据第一行,理想的对象是:
MESSAGE: SMTP_server_not_set_up PANEL : @PANEL SMTP server not set up. Contact system administrator. PAGECNT: @PAGECNT 381 SCANADFCNT :@SCANADFCNT 0 DATETIME : @DATETIME 2019-08-29T10:05:51-0400 UPTIME: @UPTIME 0:00:23
到目前为止,我可以像这样隔离重复出现的“=====”后面的 6 行:
(Select-String -Path "$PSScriptRoot$($printer)_history.log" -Pattern "=====" -Context 6).Context.PostContext
现在我需要将这些行放入自定义对象中。我真的不知道如何正确处理这个问题,我正在探索做这样的事情:
$ObjHistory = @()
(Select-String -Path "$PSScriptRoot$($printer)_history.log" -Pattern "=====" -Context 6).Context.PostContext | ForEach-Object {
if ($_ -match "PANEL") {
$properties = [ordered]@{'PANEL'="$_"}
$objet = New-Object -TypeName PSObject -Property $properties
}
$ObjHistory += $objet
}
$ObjHistory
这样我发现我可以成功地将 PANEL 属性 放入自定义对象中,它输出:
PANEL ----- @PANEL SMTP server not set up. Contact system administrator. @PANEL Load MP Feeder with Custom Type 5 Letter @PANEL Load MP Feeder with Custom Type 5 Letter @PANEL Load MP Feeder with Custom Type 5 Letter @PANEL Load MP Feeder with Custom Type 5 Letter
但是,我需要对其他行执行此操作,并且我一直不知道如何处理它,因为 ForEach-Object
一次处理一行。
提取的数据已经具有 key/value 种结构,因此您可以使用 ConvertFrom-StringData
将数据块转换为哈希表,然后转换为自定义对象。
避免在循环中附加到数组。只需输出循环中的对象,并将循环输出收集到一个变量中。
$path = "${PSScriptRoot}${printer}_history.log"
$objHistory = @(Select-String -Path $path -Pattern '=====' -Context 6 | ForEach-Object {
$props = $_.Context.PostContext -replace '^[^@]', 'MESSAGE = $&' -replace '^@(\w+)', ' = $&' |
Out-String |
ConvertFrom-StringData
New-Object -Type PSObject -Property $props
})
-replace '^[^@]', 'MESSAGE = $&'
在不以 @
开头的行前面加上字符串 MESSAGE =
,-replace '^@(\w+)', ' = $&'
替换 @WORD
开头的行符合 WORD = @WORD
。随后的 Out-String
然后将数据块合并为一个字符串,否则 ConvertFrom-StringData
将每行创建一个哈希表。
一种不同的方法
- 使用-raw参数读取登录
- 在
=====
处拆分成多个部分 - 将部分拆分为行并将这些行存储到变量中以输出为
[PSCustomObject]
编辑
- 创建一个空的
[PSCustomObject]
并使用正则表达式填充相关属性
(如果需要,清理多余的@propname)
## Q:\Test19\SO_57773555.ps1
$RE = [regex]'^@(MESSAGE|PANEL|PAGECNT|SCANADFCNT|DATETIME|UPTIME) +(.*)$'
$Path = "$PSScriptRoot$($printer)_history.log"
$ObjHistory = foreach($Section in ((Get-Content $Path -raw) -split '===== ?\r?\n' -ne '')){
$obj = [PSCustomobject]@{MESSAGE="";PANEL="";PAGECNT="";SCANADFCNT="";DATETIME="";UPTIME=""}
$obj.MESSAGE = ($Section -split '\r?\n')[0]
foreach($Line in ($Section -split '\r?\n')[1..5] ){
if($Line -match $RE){
$obj.($Matches[1])=$Matches[2] # to have the complete line =$Matches[0]
}
}
$obj
}
$ObjHistory
> .\SO_57773555.ps1
MESSAGE : SMTP_server_not_set_up
PANEL : SMTP server not set up. Contact system administrator.
PAGECNT : 381
SCANADFCNT : 0
DATETIME : 2019-08-29T10:05:51-0400
UPTIME : 0:00:23
MESSAGE : PowerOnReset
PANEL :
PAGECNT : 381
SCANADFCNT : 0
DATETIME : 2019-08-29T10:05:50-0400
UPTIME :
MESSAGE : Load_MP_Feeder_with_Custom_Type_5_Letter
PANEL : Load MP Feeder with Custom Type 5 Letter
PAGECNT : 337
SCANADFCNT : 0
DATETIME : 2019-08-29T09:59:22-0400
UPTIME : 0:44:15
尝试了 convertfrom-string,基于示例的解析。多个示例效果更好。
$template = @'
=====
{message*:SMTP_server_not_set_up}
{panel:@PANEL SMTP server not set up. Contact system administrator.}
{pagecnt:@PAGECNT 381}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T10:05:51-0400}
{uptime:@UPTIME 0:00:23}
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
{message*:PowerOnReset}
{pagecnt:@PAGECNT 381}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T10:05:50-0400}
@PORCNT 49
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
{message*:Load_MP_Feeder_with_Custom_Type_5_Letter}
{panel:@PANEL Load MP Feeder with Custom Type 5 Letter}
{pagecnt:@PAGECNT 337}
{scanadfcnt:@SCANADFCNT 0}
{datetime:@DATETIME 2019-08-29T09:59:22-0400}
{uptime:@UPTIME 0:44:15}
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
'@
$testtext = @'
=====
SMTP_server_not_set_up
@PANEL SMTP server not set up. Contact system administrator.
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:51-0400
@UPTIME 0:00:23
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
PowerOnReset
@PAGECNT 381
@SCANADFCNT 0
@DATETIME 2019-08-29T10:05:50-0400
@PORCNT 49
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
Load_MP_Feeder_with_Custom_Type_5_Letter
@PANEL Load MP Feeder with Custom Type 5 Letter
@PAGECNT 337
@SCANADFCNT 0
@DATETIME 2019-08-29T09:59:22-0400
@UPTIME 0:44:15
@CODELVL
Base MSNGM.053.023
Engine GM.052.E015
Panel f0.12p48v3
@END
=====
'@
$testText | ConvertFrom-String -TemplateContent $template
输出:
message : SMTP_server_not_set_up
panel : @PANEL SMTP server not set up. Contact system administrator.
pagecnt : @PAGECNT 381
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T10:05:51-0400
uptime : @UPTIME 0:00:23
message : PowerOnReset
pagecnt : @PAGECNT 381
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T10:05:50-0400
message : Load_MP_Feeder_with_Custom_Type_5_Letter
panel : @PANEL Load MP Feeder with Custom Type 5 Letter
pagecnt : @PAGECNT 337
scanadfcnt : @SCANADFCNT 0
datetime : @DATETIME 2019-08-29T09:59:22-0400
uptime : @UPTIME 0:44:15