[英]How to parse/pipe cmd line output using Powershell to an object
I have an *.exe that outputs this data when I run this PowerShell command:我有一个 *.exe 在运行此 PowerShell 命令时输出此数据:
& $myExe list
Where $myExe
is something like C:\\Temp\\MyExe.exe
and list
is an argument.其中
$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
The data I'm looking for is the first column of the table, but it has things like List of Runbook ID...
at the top.我要查找的数据是表格的第一列,但它在顶部有诸如
List of Runbook ID...
类的内容。 Is there a good way in PowerShell to parse this data so I can get just the table data? PowerShell 中是否有解析这些数据的好方法,以便我可以只获取表数据?
BenH's helpful answer works well with your particular input and he makes a good point in general: when you call external utilities (command-line applications), all you get back are lines of text , unlike with PowerShell-native commands that pass objects around. BenH的有用答案非常适合您的特定输入,并且总的来说很不错:当您调用外部实用程序 (命令行应用程序)时,返回的只是文本行 ,而与传递对象的 PowerShell本机命令不同。
Parsing strings (text) will always be more brittle than dealing with objects (which is why PowerShell's fundamental object orientation represents a great evolutionary leap in shell design). 解析字符串 (文本)总是比处理对象更加脆弱 (这就是为什么PowerShell的基本面向对象代表了Shell设计方面的巨大飞跃)。
That said, if you can make certain assumptions about the formatting of the strings you receive, PowerShell offers great tools to help even with that : 就是说, 如果您可以对接收到的字符串的格式做出某些假设,那么PowerShell将提供出色的工具来帮助您 :
Imagine a function Select-Column
that selects whitespace-separated fields (column values) by index from each input line (vaguely akin to awk
): 想象一下一个
Select-Column
函数 ,该函数通过索引从每条输入行(大概类似于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
The above, due to selecting the 1st column ( -Index 0
- multiple indices supported) from only those lines that have exactly 3 fields ( -RequiredCount 3
), would yield: 上面的代码,由于仅从那些正好具有3个字段(
-RequiredCount 3
)的行中选择第一列( -Index 0
支持多个索引),将产生:
ALMService
AOSService
BIService
DevToolsService
DIXFService
MROneBox
PayrollTaxModule
PerfSDK
ReportingService
RetailCloudPos
RetailHQConfiguration
RetailSDK
RetailSelfService
RetailServer
RetailStorefront
SCMSelfService
Select-Column
source code: Select-Column
源代码: Note that if you specify multiple ( 0
-based) column indices, the output fields are tab -separated by default, which you can change with the -OutFieldSeparator
parameter. 请注意,如果您指定多个(基于
0
的)列索引,则默认情况下,输出字段以制表符- -OutFieldSeparator
,您可以使用-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
}
}
}
You could save the output in a variable, use Where-Object
to filter just the lines that have Version
in it, then remove all the unwanted characters with a -replace
regex. 您可以将输出保存在变量中,使用
Where-Object
过滤其中包含Version
的行,然后使用-replace
regex删除所有不需要的字符。
$myExeOutput = & $myExe list
$myExeOutput |
Where-Object {$_ -match 'Version:'} |
ForEach-Object {
$_ -replace '\s+Version:.*$',''
}
@mklement0 This is brilliant! @mklement0 这太棒了! I used it to parse the output of "winrm get winrm/config/service" (which is a mess) to check whether or not Basic Authentication is allowed.
我用它来解析“winrm get winrm/config/service”的输出(这是一团糟),以检查是否允许基本身份验证。 I called your function with:
我用以下方法调用了您的函数:
$cmd = "winrm get winrm/config/service"
$keys = @(Invoke-Expression $cmd | Select-Column -Index 0 -RequiredCount 4)
$values = @(Invoke-Expression $cmd | Select-Column -Index 2 -RequiredCount 4)
foreach ($key in $keys) {
Write-Host "$($key) = $($values)" -ForegroundColor Green
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.