Существуют ли инструменты для обработки текстового вывода и передачи его в динамический объект, который можно запрашивать как столбцы?
В частности, я призываю ..
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).
решение1
Ничего встроенного нет.
Однако не должно быть слишком сложно создать помощника (конечно, в модуле для простоты повторного использования), который берет определение каждого столбца (например, имя, начальную позицию, длину, тип, ...; или, возможно, альтернативные критерии для разделения столбцов, если длину невозможно определить заранее) и создает пользовательский объект.
решение2
Многие из этих утилит до PowerShell запрашивают различные базовые API Windows, такие как WMI. Прежде чем углубляться в анализ текста, я бы попытался выяснить, откуда утилита берет информацию, и начать оттуда. В вашем конкретном случае я не удивлюсь, если она на самом деле запрашивает класс WMI Win32_LogonSession, который вы можете легко перечислить с помощью PowerShell — и получить обратно правильно отформатированные объекты. Такой подход может не работать во всех ситуациях, но это было бы хорошим местом для начала, по крайней мере.
$users = get-wmiobject -query "Select * from Win32_LogonSession"
Если немного погуглить, то это выглядит как многообещающая функция для того, что вам нужно: функция get-loggedonuser
решение3
Это комментарий к ответу Ричарда.
Вот что я придумал. Можно было бы 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;
}