Назад | Перейти на главную страницу

Как в PowerShell проанализировать предварительно отформатированный вывод?

Существуют ли существующие инструменты для вывода текстового вывода и передачи его динамическому объекту, который можно запрашивать как столбцы?

В частности, я призываю ..

query session /server:MYSERVER

.. который выводит ..

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

Это моя первая задача в роли DevOps - действовать в соответствии с этим выводом на основе условий столбцов, но после нескольких попыток конвейерной передачи в foreach и т. Д. Я понял, что это всего лишь несколько строк строк.

Я надеялся на что-то вроде ..

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     

Единственное решение, которое я нашел, - это извлечение столбцов вручную с помощью String.Substring (). Я надеялся, что есть инструменты PowerShell, которые это автоматизируют.

[[Это пример,]], но некоторые столбцы пусты, а столбцы с фиксированной шириной не имеют одинаковой ширины между собой, поэтому разбор этого будет намного более ручным, чем приведенные там примеры. Я надеялся, что обновления версии Powershell, возможно, будут иметь лучший инструментарий?

Используется Windows Server 2012 R2 (с PowerShell 4).

Нет ничего встроенного.

Однако не должно быть слишком сложно создать помощник (в модуле для удобного повторного использования, конечно), который принимает определение каждого столбца (например, имя, начальную позицию, длину, тип, ...; или, возможно, альтернативные критерии для разделить столбцы, если длину невозможно определить заранее) и создает настраиваемый объект.

Это комментарий к ответу Ричарда.

Вот что я придумал. Можно выполнить foreach {} во всех строках (кроме первой строки, которая является $ 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 запрашивают различные базовые API Windows, такие как WMI. Прежде чем углубиться в синтаксический анализ текста, я бы попытался найти, откуда утилита получает информацию, и начать с этого. В вашем конкретном случае я не удивлюсь, если он действительно запрашивает WMI-класс Win32_LogonSession, который вы можете легко перечислить с помощью PowerShell - и получить обратно правильно отформатированные объекты. Этот подход может работать не во всех ситуациях, но, по крайней мере, с него можно начать.

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

Если немного погуглить, это выглядит многообещающей функцией для того, что вам нужно: функция get-loggedonuser