从基于文本的表格输出中提取列

问题描述 投票:0回答:4

qfarm /load
命令显示我的服务器的负载。 输出:

PS> qfarm /load

Server Name           Server Load  Load Throttling Load  Logon Mode
--------------------  -----------  --------------------  ------------------
SERVER-01             400          0                     AllowLogons
SERVER-02             1364         OFF                   AllowLogons
SERVER-03             1364         OFF                   AllowLogons
SERVER-04             1000         0                     AllowLogons
SERVER-05             700          0                     AllowLogons
SERVER-06             1200         0                     AllowLogons

我只需要显示第一列(服务器名称)和第二列(服务器负载)并循环它们,以便稍后进行一些逻辑,但似乎powershell没有将其视为具有属性的对象:

PS> qfarm /load | Select -ExpandProperty "Server Name"
Select-Object : Property "Server Name" cannot be found.

还有其他可能性吗,比如桌子之类的?

powershell properties multiple-columns
4个回答
5
投票

实现此目的的一种方法是从命令的输出中构建对象。测试了以下内容:

#requires -version 3

# sample data output from command
$sampleData = @"
Server Name           Server Load  Load Throttling Load  Logon Mode
--------------------  -----------  --------------------  ------------------
SERVER-01             400          0                     AllowLogons
SERVER-02             1364         OFF                   AllowLogons
SERVER-03             1364         OFF                   AllowLogons
SERVER-04             1000         0                     AllowLogons
SERVER-05             700          0                     AllowLogons
SERVER-06             1200         0                     AllowLogons
"@ -split "`n"

$sampleData | Select-Object -Skip 2 | ForEach-Object {
  $len = $_.Length
  [PSCustomObject] @{
    "ServerName"         = $_.Substring(0,  22).Trim()
    "ServerLoad"         = $_.Substring(22, 13).Trim() -as [Int]
    "LoadThrottlingLoad" = $_.Substring(35, 22).Trim()
    "LogonMode"          = $_.Substring(57, $len - 57).Trim()
  }
}

在您的情况下,您应该能够将

$sampleData
替换为
qfarm load
命令;例如:

qfarm /load | Select-Object -Skip 2 | ForEach-Object {
...

当然,这是假设输出中没有空行,并且我的每个项目开头的列位置是正确的。

PowerShell 版本 2 等效项:

#requires -version 2

function Out-Object {
  param(
    [Collections.Hashtable[]] $hashData
  )
  $order = @()
  $result = @{}
  $hashData | ForEach-Object {
    $order += ($_.Keys -as [Array])[0]
    $result += $_
  }
  New-Object PSObject -Property $result | Select-Object $order
}

# sample data output from command
$sampleData = @"
Server Name           Server Load  Load Throttling Load  Logon Mode
--------------------  -----------  --------------------  ------------------
SERVER-01             400          0                     AllowLogons
SERVER-02             1364         OFF                   AllowLogons
SERVER-03             1364         OFF                   AllowLogons
SERVER-04             1000         0                     AllowLogons
SERVER-05             700          0                     AllowLogons
SERVER-06             1200         0                     AllowLogons
"@ -split "`n"

$sampleData | Select-Object -Skip 2 | ForEach-Object {
  $len = $_.Length
  Out-Object `
    @{"ServerName"         = $_.Substring(0,  22).Trim()},
    @{"ServerLoad"         = $_.Substring(22, 13).Trim() -as [Int]},
    @{"LoadThrottlingLoad" = $_.Substring(35, 22).Trim()},
    @{"LogonMode"          = $_.Substring(57, $len - 57).Trim()}
}

4
投票

您可以使用 PowerShell Gallery

 中的 
ConvertFrom-SourceTable cmdlet 轻松将表转换为 PowerShell 对象:

Install-Script -Name ConvertFrom-SourceTable

$sampleData = ConvertFrom-SourceTable @"
Server Name           Server Load  Load Throttling Load  Logon Mode
--------------------  -----------  --------------------  ------------------
SERVER-01             400          0                     AllowLogons
SERVER-02             1364         OFF                   AllowLogons
SERVER-03             1364         OFF                   AllowLogons
SERVER-04             1000         0                     AllowLogons
SERVER-05             700          0                     AllowLogons
SERVER-06             1200         0                     AllowLogons
"@

然后选择您的列,例如:

PS C:\> $SampleData | Select-Object "Server Name", "Server Load"

Server Name Server Load
----------- -----------
SERVER-01   400
SERVER-02   1364
SERVER-03   1364
SERVER-04   1000
SERVER-05   700
SERVER-06   1200

详情请参阅:

ConvertFrom-SourceTable -?

ConvertFrom-SourceTable
cmdlet 可以在 PowerShell Gallery 下载,源代码可以从 GitHub
iRon7/ConvertFrom-SourceTable
存储库下载。


1
投票

命令行实用程序将其输出作为字符串数组返回。这应该有效:

qfarm /load | ForEach-Object { $_.Substring(0,33) }

0
投票

我过去回答过与此非常相似的问题。我有一个更大的函数,但简化了左对齐字符串表的工作,正如您在示例中所示的那样。请参阅链接的答案以获取更多说明。

function ConvertFrom-LeftAlignedStringData{
    param (
        [string[]]$data
    )

    $headerString = $data[0]
    $headerElements = $headerString -split "\s{2,}" | Where-Object{$_}
    $headerIndexes = $headerElements | ForEach-Object{$headerString.IndexOf($_)}

    $results = $data | Select-Object -Skip 2  | ForEach-Object{
        $props = @{}
        $line = $_
        For($indexStep = 0; $indexStep -le $headerIndexes.Count - 1; $indexStep++){
            $value = $null            # Assume a null value 
            $valueLength = $headerIndexes[$indexStep + 1] - $headerIndexes[$indexStep]
            $valueStart = $headerIndexes[$indexStep]
            If(($valueLength -gt 0) -and (($valueStart + $valueLength) -lt $line.Length)){
                $value = ($line.Substring($valueStart,$valueLength)).Trim()
            } ElseIf ($valueStart -lt $line.Length){
                $value = ($line.Substring($valueStart)).Trim()
            }
            $props.($headerElements[$indexStep]) = $value    
        }
        New-Object -TypeName PsCustomObject -Property $props
    } 

    return $results
}


$qfarmOutput = qfarm /load
ConvertFrom-LeftAlignedStringData $qfarmOutput | select "Server Name","Server Load"

此方法基于标头字段的位置。没有什么是硬编码的,它都是基于这些索引和字段名称自定义构建的。使用这些

$headerIndexes
,我们分割每一行并将结果(如果存在)放入相应的列中。有逻辑确保我们不会尝试抓取字符串中可能不存在的任何部分,并将最后一个字段特殊对待。

结果

Server Name Server Load
----------- -----------
SERVER-01   400        
SERVER-02   1364       
SERVER-03   1364       
SERVER-04   1000       
SERVER-05   700        
SERVER-06   1200       
© www.soinside.com 2019 - 2024. All rights reserved.