注意:下面的代码是将纯文本数据解析为对象以实现更健壮、更灵活的处理的练习。
然而,理想情况下,处理应该从对象而不是纯文本开始,这就是为什么从PowerShell cmdlet等Get-Service
而不是从外部实用程序输出的文本开始是更可取的原因。
假设每个输入文件中的所有条目在各自的其他文件中都有匹配的服务器 + 服务名称条目:
$f1, $f2 = "c:\temp\mek\123-first.txt", "c:\temp\mek\123-second.txt"
Compare-Object (Get-Content $f1) (Get-Content $f2) | ForEach-Object {
$i = 0; $ht = @{}; $vals = -split $_.InputObject
foreach($col in 'Server', 'Service', 'State', 'Mode') {
$ht.$col = $vals[$i++]
}
$ht.Before = $_.SideIndicator -eq '<='
[pscustomobject] $ht
} | Group-Object Server, Service | ForEach-Object {
$ndxBefore, $ndxAfter = if ($_.Before) { 0, 1 } else { 1, 0 }
[pscustomobject] @{
Server = $_.Group[0].Server
Service = $_.Group[0].Service
'State Before' = $_.Group[$ndxBefore].State
'Mode Before' = $_.Group[$ndxBefore].Mode
'State After' = $_.Group[$ndxAfter].State
'Mode After' = $_.Group[$ndxAfter].Mode
}
} | Sort-Object Server, Service |
Format-Table
笔记:
以上格式输出显示(使用Format-Table
),而不将其发送到文件。
您可以追加| Out-File "c:\temp\mek\results.txt"
以将相同的表示保存到文件中。
但是,请注意,Format-Table
应用 before 命令会返回具有各个属性的对象,因此您可以以各种格式输出到文件,例如使用Export-Csv
, 例如。
示例输出:
Server Service State Before Mode Before State After Mode After
------ ------- ------------ ----------- ----------- ----------
D7MCYP AdobeFlashPlayerUpdateSvc Stopped Manual Stopped Auto
D7MCYP AeLookupSvc Stopped Manual Started Manual
说明:
使用单个长管道,这使得代码简洁且内存高效。
管道分解如下:
比较:
Compare-Object
Get-Content
比较调用返回的两个输入文件中的行数组,并输出表示发现差异[pscustomobject]
的实例,字符串属性指示手头的行(可通过 访问)对于 LHS(第一个输入文件)是否唯一 - - 或RHS(第二个输入文件)-.SideIndicator
.InputObject
<=
>=
转换为自定义对象:
为每个输入对象(表示为 )执行{ ... }
传递给的脚本块 ( )。ForEach-Object
$_
-split $_.InputObject
通过空格将手头的“差异线”拆分为字段,并将结果字段作为数组存储在$vals
.
$ht
是一个辅助哈希表,用于将字段值映射到字段名称。
$ht.Before
添加一个布尔条目以指示手头的差异行是否来自“前文件”(第一个输入文件)。
[pscustomobject] $ht
转换辅助。hashtable 到一个自定义对象并输出它(通过管道发送它)。
分组:
Group-Object
用于对生成的对象进行分组,可以通过共享值Server
和Service
属性值,生成一个[Microsoft.PowerShell.Commands.GroupInfo]
代表每个分组的实例。
转换为组合自定义对象:
同样,ForEach-Object
用于执行每个输入对象的处理。
[pscustomobject] @{ ... }
用于构造每个组合输出对象,同样使用辅助哈希表。
$_.Group
包含形成每个组的输入对象——在我们的例子中,$_.Group[0]
是$_.Group[1]
表示给定服务器-服务组合的转换为对象的输入行。
根据定义,两个输入对象都具有相同的.Server
和.Service
值,因此盲目地使用$_.Group[0]
组合输出对象的值即可。
相比之下,* Before
and* After
属性是适当的输入对象(无论是来自第一个文件还是第二个文件),这就是为什么通过先前添加的属性相应地选择数组索引$ndxBefore
和$ndxAfter
.Before
排序:
Sort-Object
按指定的属性对结果对象进行排序。
输出格式:
- 输出格式 cmdlet
Format-Table
确保已排序的对象以表格形式呈现。