2

我试图把比较对象的输出。我是 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服务):

系统名称 名称 状态 启动模式
---------- ---- ----- ---------
D7MCYP Adob​​eARM 服务自动停止     
D7MCYP Adob​​eFlashPlayerUpdateSvc 停止手册   
D7MCYP AeLookupSvc 停止手册   

我的比较对象结果如下:

BL3C4V wudfsvc 自动停止
BL3C4V wudfsvc 停止手册   
D7MCYP Adob​​eARMservice 自动运行     
D7MCYP Adob​​eARM 服务自动停止     

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

服务器服务前状态前模式后状态后模式
BL3C4V wudfsvc 停止自动停止手动
D7MCYP Adob​​eARMservice 运行自动停止自动     
4

1 回答 1

1

注意:下面的代码是将纯文本数据解析为对象以实现更健壮、更灵活的处理的练习
然而,理想情况下,处理应该对象而不是纯文本开始,这就是为什么PowerShell cmdletGet-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-ObjectGet-Content比较调用返回的两个输入文件中的行数组,并输出表示发现差异[pscustomobject]的实例,字符串属性指示手头的行(可通过 访问)对于 LHS(第一个输入文件)是否唯一 - - 或RHS(第二个输入文件)-.SideIndicator.InputObject<=>=
  • 转换为自定义对象:

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

    • -split $_.InputObject通过空格将手头的“差异线”拆分为字段,并将结果字段作为数组存储在$vals.

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

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

    • [pscustomobject] $ht转换辅助。hashtable 到一个自定义对象并输出它(通过管道发送它)。

  • 分组:

    • Group-Object用于对生成的对象进行分组,可以通过共享值ServerService属性值,生成一个[Microsoft.PowerShell.Commands.GroupInfo]代表每个分组的实例。
  • 转换为组合自定义对象:

    • 同样,ForEach-Object用于执行每个输入对象的处理。

    • [pscustomobject] @{ ... }用于构造每个组合输出对象,同样使用辅助哈希表。

    • $_.Group包含形成每个组的输入对象——在我们的例子中,$_.Group[0]$_.Group[1]表示给定服务器-服务组合的转换为对象的输入行。

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

    • 相比之下,* Beforeand* After属性是适当的输入对象(无论是来自第一个文件还是第二个文件),这就是为什么通过先前添加的属性相应地选择数组索引$ndxBefore$ndxAfter.Before

  • 排序:

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

    • 输出格式 cmdletFormat-Table确保已排序的对象以表格形式呈现。
于 2017-06-16T15:59:03.690 回答