如何使用Powershell将cmd行输出解析/管道输出到对象

时间:2017-07-27 17:48:37

标签: powershell parsing cmd

运行此PowerShell命令时,我有一个* .exe输出此数据:

& $myExe list

其中$myExe类似于C:\Temp\MyExe.exe,而list是一个参数。

List of Runbook ID on the system: 



List of services installed on the system: 

ALMService   Version: 7.0.4542.16189
AOSService   Version: 7.0.4542.16189
BIService    Version: 7.0.4542.16189
DevToolsService  Version: 7.0.4542.16189
DIXFService  Version: 7.0.4542.16189
MROneBox     Version: 7.1.1541.3036
PayrollTaxModule     Version: 7.1.1541.3036
PerfSDK  Version: 7.0.4542.16189
ReportingService     Version: 7.0.4542.16189
RetailCloudPos   Version: 7.1.1541.3036
RetailHQConfiguration    Version: 7.1.1541.3036
RetailSDK    Version: 7.1.1541.3036
RetailSelfService    Version: 7.1.1541.3036
RetailServer     Version: 7.1.1541.3036
RetailStorefront     Version: 7.1.1541.3036
SCMSelfService   Version: 7.1.1541.3036

我正在寻找的数据是表格的第一列,但顶部有List of Runbook ID...之类的内容。在PowerShell中有一种解析这些数据的好方法,所以我只能得到表格数据吗?

2 个答案:

答案 0 :(得分:4)

BenH's helpful answer适用于您的特定输入,他总体上提出了一个很好的观点:当您调用外部实用程序(命令行应用程序)时,您所得到的只是文本行,与传递对象的PowerShell本机命令不同。

解析字符串(文本)总是比处理对象 更脆弱(这就是为什么PowerShell的基本面向对象代表了一个伟大的进化壳设计的飞跃)。

那就是说,如果你可以对你收到的字符串的格式做出某些假设,PowerShell提供了很好的工具来帮助解决这个问题

想象一下函数Select-Column ,它从每个输入行中选择 index 的空白分隔字段(列值)(模糊地类似于awk ):

@'
List of Runbook ID on the system: 



List of services installed on the system: 

ALMService   Version: 7.0.4542.16189
AOSService   Version: 7.0.4542.16189
BIService    Version: 7.0.4542.16189
DevToolsService  Version: 7.0.4542.16189
DIXFService  Version: 7.0.4542.16189
MROneBox     Version: 7.1.1541.3036
PayrollTaxModule     Version: 7.1.1541.3036
PerfSDK  Version: 7.0.4542.16189
ReportingService     Version: 7.0.4542.16189
RetailCloudPos   Version: 7.1.1541.3036
RetailHQConfiguration    Version: 7.1.1541.3036
RetailSDK    Version: 7.1.1541.3036
RetailSelfService    Version: 7.1.1541.3036
RetailServer     Version: 7.1.1541.3036
RetailStorefront     Version: 7.1.1541.3036
SCMSelfService   Version: 7.1.1541.3036
'@ -split '\r?\n' | 
  Select-Column -Index 0 -RequiredCount 3

以上,由于选择了第1列(-Index 0 - 支持的多个索引),只有那些只有3个字段(-RequiredCount 3)的行才会产生:

ALMService
AOSService
BIService
DevToolsService
DIXFService
MROneBox
PayrollTaxModule
PerfSDK
ReportingService
RetailCloudPos
RetailHQConfiguration
RetailSDK
RetailSelfService
RetailServer
RetailStorefront
SCMSelfService

Select-Column源代码:

请注意,如果指定多个(0 - )列索引,默认情况下输出字段为 tab -separated,您可以使用-OutFieldSeparator参数进行更改

Function Select-Column {
  [cmdletbinding(PositionalBinding=$False)]
  param(
    [Parameter(ValueFromPipeline, Mandatory)]
    $InputObject,

    [Parameter(Mandatory, Position=0)]
    [int[]] $Index,

    [Parameter(Position=1)]
    [int] $RequiredCount,

    [Parameter(Position=2)]
    [string] $OutFieldSeparator = "`t"

  )

  process {
    if (($fields = -split $InputObject) -and ($RequiredCount -eq 0 -or $RequiredCount -eq $fields.Count)) {
      $fields[$Index] -join $OutFieldSeparator
    }
  }

}

答案 1 :(得分:3)

您可以将输出保存在变量中,使用Where-Object仅过滤其中包含Version的行,然后使用-replace正则表达式删除所有不需要的字符。

$myExeOutput = & $myExe list
$myExeOutput |
    Where-Object {$_ -match 'Version:'} |
    ForEach-Object {
        $_ -replace '\s+Version:.*$',''
    }