在PowerShell中,如何parsing预格式化的输出?

有没有现成的工具来采取基于文本的输出,并将其pipe道到一个dynamic的对象,可以查询为列?

具体来说,我正在调用..

query session /server:MYSERVER 

..这是输出..

 SESSIONNAME USERNAME ID STATE TYPE DEVICE services 0 Disc console Jon 1 Active 

这是我在DevOpsangular色中的第一个任务,根据列的条件对这个输出进行操作,但是在多次尝试inputforeach等之后,我意识到这只是多行string。

我所希望的是…

 query session /server:MYSERVER | foreach ` { ` if ($_.Username -eq "Jon") ` {` custom-action $_.ID ` } ` } 

(请注意,我不一定需要评估用户名,或者不只是用户名,我只是在这个例子中。

显然这是行不通的,因为这..

 query session /server:192.168.1.103 | foreach { echo $_.GetType() } 

..输出这个..

 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object True True String System.Object True True String System.Object 

我发现的唯一解决scheme是使用String.Substring()手动提取列。 我希望有PowerShell工具,这自动化。

[[ 这是一个例子 ]],但有些列是空白的,固定宽度的列之间不是相同的宽度,所以parsing这个将比那里​​的例子更加手动。 我希望Powershell版本更新可能有更好的工具?

使用Windows Server 2012 R2(具有PowerShell 4)。

没有内置任何东西。

然而,创build一个帮助器(在一个容易被重用的模块中)并不难,它需要每个列的定义(例如名称,起始位置,长度,types,…或者可能的替代标准如果长度不能被预先确定,则将这些列分开)并创build一个自定义对象。

这是理查德回应的评论。

这是我想出来的。 在所有行上(除了第一行,即$ head),都可以{}传递给这个函数。

 Function ParseFixedWidthCols($head,$line) { $colnamematches = $head | select-string "(\s*\w+\b\s*)" -allmatches | foreach { $_.matches } $cols = @() for ($ci=0; $ci -lt $colnamematches.Count; $ci++) { $col = $colnamematches[$ci].Value $cols += $col } $col = $cols[0] $ret = New-Object PSObject $cc = 0 for ($ci=0; $ci -lt $cols.Count; $ci++) { $value = $line.Substring($cc, $cols[$ci].Length) $ret | Add-Member -MemberType NoteProperty -name $cols[$ci].Trim() -value $value.Trim() $cc += $cols[$ci].Length } return ret; } 

许多这些PowerShell之前的实用程序查询各种底层Windows API,如WMI。 在挖掘文本parsing之前,我会尝试findutil从哪里获取信息,并从那里开始。 对于您的具体情况,如果实际上查询可以使用PowerShell轻松枚举的Win32_LogonSession WMI类并获取格式正确的对象,我不会感到惊讶。 这种方法在所有情况下都可能不起作用,但至less可以开始。

 $users = get-wmiobject -query "Select * from Win32_LogonSession" 

通过一些search引擎,这看起来像一个有前途的function,你需要: get-loggedonuser函数