Синтаксический анализ выходных данных PowerShell в виде таблицы - PullRequest
0 голосов
/ 06 июля 2018

PowerShell возвращает мне этот вывод при запуске команды:

PS Output

Mod  Ports  Module-Type                         Model              Status
---  -----  -----------                         ------------------ ----------
1    48     2/4/8/10/16 Gbps Advanced FC Module DS-X9448-768K9     ok
2    48     2/4/8/10/16 Gbps Advanced FC Module DS-X9448-768K9     ok
3    0      Supervisor Module-3                 DS-X97-SF1-K9      ha-standby
4    0      Supervisor Module-3                 DS-X97-SF1-K9      active *

У меня возникают проблемы при попытке его разбить, потому что он не разделен табуляцией, разделен пробелом, поэтому при использовании .split("") столбец Module-Type разделяется неправильно, поскольку в его содержимом также есть пробелы.

Я новичок в этом, любая помощь будет оценена.

Вот мой код:

$RS = .\Plink server@puttysession -pw "password" "command"

foreach ($RSln in $RS){
    $arr = $RSln.split('',[System.StringSplitOptions]::RemoveEmptyEntries)
    Write-Host $RSln "|" $arr.Length
}

Это дает мне строку и длину созданного массива, первые две строки являются массивами с длиной 5, третья и четвертая имеют 9 элементов из-за пробелов в ModuleType

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Большинство сценаристов PowerShell, вероятно, сказали бы, что это плохая идея использовать любые текстовые таблицы, подобные выводу Format-Table, в качестве входных данных, но мне нравится оспаривать это, потому что отформатированные исходные таблицы могут быть прочитаны людьми, и если люди могут читать их и определить, например, компоновка относительно того, где столбец начинается и заканчивается, программа должна быть в состоянии сделать то же самое ...

В некоторых случаях (например, для примеров данных на сайте StackOverflow ) это может быть даже удобнее, чем другие форматы, такие как CSV (, которые трудно читать и поддерживают только строковые данные ), XML (, что очень многословно и поэтому также трудно читать ) или JSON (или PSON, , что лучше для сложных данных но не для списка объектов, которые содержат простые собственные свойства )

Исходя из этой мысли, я написал многоразовый ConvertFrom-SourceTable командлет , который доступен для загрузки в галерее PowerShell, и исходный код GitHub iRon7/ConvertFrom-SourceTable хранилище.

В вашем случае команда для преобразования таблицы в объект так же проста, как $RS | ConvertFrom-SourceTable, позвольте мне показать, что:

$RS = '
    Mod Ports Module-Type                        Model              Status
    --- ----- ---------------------------------- ------------------ -----------
    1   48    2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9     ok
    2   48    2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9     ok
    3   0     Supervisor Module-3                DS-X97-SF1-K9      ha-standby
    4   0     Supervisor Module-3                DS-X97-SF1-K9      active *
'

$RS | ConvertFrom-SourceTable

Status      : ok
Model       : DS-X9448-768K9
Ports       : 48
Mod         : 1
Module-Type : 2/4/8/10/16 Gbps Advance FC Module

Mod         : 2
Module-Type : 2/4/8/10/16 Gbps Advance FC Module
Ports       : 48
Model       : DS-X9448-768K9
Status      : ok

Mod         : 3
Module-Type : Supervisor Module-3
Ports       : 0
Model       : DS-X97-SF1-K9
Status      : ha-standby

Mod         : 4
Module-Type : Supervisor Module-3
Ports       : 0
Model       : DS-X97-SF1-K9
Status      : active *

И так как все ваши данные выровнены по левому краю (и каждому столбцу понадобится заголовок), расположение столбцов можно определить с самого начала, что означает, что вы можете даже stream этот ввод таблицы (предполагая, что .\Plink выводит каждую строку отдельно) через конвейер:

.\Plink server@puttysession -pw "password" "command" | ConvertFrom-SourceTable

(То есть, если вы предоставляете исходную таблицу в виде многострочной строки, командлет ConvertFrom-SourceTable будет определять ведьмы столбцов для всей таблицы, в противном случае он будет основан на заголовке, прошлых и текущих записях)

Если исходные таблицы будут иметь лучшее соглашение о форматировании, например, "нестроковые данные (данные, которые должны быть интерпретированы) выровнены по правому краю" (как на самом деле сделано Format-Table). Можно предположить (как это сделал @Ansgar Wiechers), что Mod и Ports - это целые числа. Например:

$Object = ConvertFrom-SourceTable '
    Mod Ports Module-Type                        Model          Status
    --- ----- -----------                        -----          ------
      1    48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
      2    48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
      3     0 Supervisor Module-3                DS-X97-SF1-K9  ha-standby
      4     0 Supervisor Module-3                DS-X97-SF1-K9  ha-standby
'

(обратите внимание, что в этом примере $Object | Format-Table даст тот же вывод, что и вход)

Для дополнительных примеров используйте справку: Help ConvertFrom-SourceTable -Full

0 голосов
/ 06 июля 2018

Рекомендованный способ обработки ввода такого рода в PowerShell - это анализ его в пользовательских объектах. Вы можете сделать это либо с помощью регулярного выражения:

$RS | Where-Object {
    $_ -match '(\d+)\s+(\d+)\s+(.*?)\s+([a-z]+(?:-[a-z0-9]+){2,})\s+(.*)'
} | ForEach-Object {
    New-Object -Type PSObject -Property @{
        'Mod'        = [int]$matches[1]
        'Ports'      = [int]$matches[2]
        'ModuleType' = $matches[3]
        'Model'      = $matches[4]
        'Status'     = $matches[5]
    }
}

или (если столбцы имеют фиксированную ширину) путем извлечения подстрок с заданными смещениями:

$RS | Select-Object -Skip 2 | ForEach-Object {
    New-Object -Type PSObject -Property @{
        'Mod'        = [int]$_.Substring(0, 3).Trim()
        'Ports'      = [int]$_.Substring(5, 5).Trim()
        'ModuleType' = $_.Substring(12, 35).Trim()
        'Model'      = $_.Substring(48, 18).Trim()
        'Status'     = $_.Substring(67).Trim()
    }
}

Select-Object -Skip 2 необходим для пропуска 2 строк заголовка.

Если бы все столбцы были разделены более чем одним пробелом через -split '\s\s+' (разделение на 2 или более последовательных пробельных символа), тоже сработало бы. Однако с вашими данными это не так, поскольку по крайней мере первые 2 строки данных имеют только один пробел между 3-м и 4-м столбцами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...