每个项目的Powershell比较对象输出1行

时间:2017-06-16 15:02:10

标签: powershell compareobject

我试图输入compare-object的输出。我是Powershell的新手,不幸的是还不知道这些细节。

我的命令如下:

Compare-Object -referenceObject $(Get-Content "c:\temp\mek\123-first.txt") -differenceObject $(Get-Content "c:\temp\mek\123-second.txt") | %{$_.Inputobject} | sort-object | out-file "c:\temp\mek\results.txt"

我的文件内容如下(只是比较Windows服务):

systemname name                                         state   startmode
---------- ----                                         -----   ---------
D7MCYP     AdobeARMservice                              Stopped Auto     
D7MCYP     AdobeFlashPlayerUpdateSvc                    Stopped Manual   
D7MCYP     AeLookupSvc                                  Stopped Manual   

我的compare-object结果如下:

BL3C4V     wudfsvc                                      Stopped Auto
BL3C4V     wudfsvc                                      Stopped Manual   
D7MCYP     AdobeARMservice                              Running Auto     
D7MCYP     AdobeARMservice                              Stopped Auto     

现在,如果有人可以帮助输出以保持每个服务器的前2列和列3,4的不同值到新列(5,6)。如果我也获得头衔也会很好。例如:

Server      Service             Before State    Before Mode     After State  After Mode
BL3C4V      wudfsvc             Stopped         Auto            Stopped         Manual
D7MCYP      AdobeARMservice     Running         Auto            Stopped         Auto     

1 个答案:

答案 0 :(得分:0)

注意:下面的代码是将纯文本数据解析为对象的练习,以实现更强大,更灵活的处理
但是,理想情况下,处理应以对象而不是纯文本开始,  这就是 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之前的命令 - 返回带有各个属性的对象,因此您可以输出各种格式的文件,例如例如,使用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]个实例,带有字符串属性.SideIndicator指示当前行(可通过.InputObject访问)是否对LHS(第一个输入文件) - <= - 或RHS(第二个输入文件) - {{{ 1}}
  • 转换为自定义对象:

    • 为每个输入对象(表示为>=)执行传递给{ ... }的脚本块(ForEach-Object)。

    • $_通过空格运行将“差异线”拆分为字段,并将结果字段存储为-split $_.InputObject中的数组。

    • $vals是一个辅助哈希表,用于将字段值映射到字段名称。

    • $ht添加一个布尔条目,以指示手边的差异线是否来自“之前的文件”(第一个输入文件)。

    • $ht.Before转换辅助。哈希表进入自定义对象并输出(通过管道发送)。

  • 分组:

    • [pscustomobject] $ht用于通过共享Group-ObjectServer属性值对结果对象进行分组,从而生成代表每个分组的Service实例。
  • 转换为组合自定义对象:

    • 同样,[Microsoft.PowerShell.Commands.GroupInfo]用于执行每个输入对象的处理。

    • ForEach-Object用于构建每个组合输出对象,同样使用辅助哈希表。

    • [pscustomobject] @{ ... }包含构成每个组的输入对象 - 在我们的示例中,$_.Group$_.Group[0]是表示给定服务器服务的转换为对象的输入行组合

    • 根据定义,两个输入对象都具有相同的$_.Group[1].Server值,因此盲目地使用组合输出对象的.Service值将会这样做。

    • 相比之下,$_.Group[0]* Before属性是相应的输入对象(无论是来自第一个还是第二个文件),这就是数组索引* After和{{通过之前添加的$ndxBefore属性

    • 相应地选择1}}
  • 排序:

    • $ndxAfter按指定的属性对结果对象进行排序。
  • 输出格式:

    • 输出格式化cmdlet .Before可确保已排序的对象显示为