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

时间:2017-11-16 17:28:15

标签: powershell properties multiple-columns

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.

还有其他可能性,比如桌子还是什么?

4 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是从命令的输出中构建对象。测试了以下内容:

#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; e.g:

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()}
}

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

I have answered something very similar to this in the past。我有一个更大的功能,但在左对齐字符串表上的简化工作正如您在示例中所示。有关更多说明,请参阅链接的答案。

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       

答案 3 :(得分:0)

您可以使用ConvertFrom-SourceTable中的PowerShell Gallery cmdlet轻松将表格转换为PowerShell对象:

$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库中下载,而GitHub iRon7/ConvertFrom-SourceTable存储库中可以找到源代码。