Вывод объекта сравнения Powershell 1 строка на элемент

Я пытаюсь вывести результат сравнения объекта. Я новичок в Powershell и, к сожалению, пока не знаю все подробности.

Моя команда выглядит следующим образом:

Compare-Object -referenceObject $(Get-Content "c:\temp\mek\123-first.txt") -differenceObject $(Get-Content "c:\temp\mek\123-second.txt") | %{$_.Inputobject} | sort-object | out-file "c:\temp\mek\results.txt"

Содержимое моих файлов выглядит следующим образом (просто сравнивая службы Windows):

имя системы
---------- ----                                         -----   ---------
D7MCYP     AdobeARMservice остановлен авто     
D7MCYP     AdobeFlashPlayerUpdateSvc Остановлено вручную   
D7MCYP     AeLookupSvc Остановлено руководство   

Мои результаты сравнения объекта следующие:

BL3C4V     wudfsvc остановлен авто
BL3C4V     wudfsvc Остановлено руководство   
D7MCYP AdobeARMservice Запуск Авто     
D7MCYP AdobeARMservice остановлен авто     

Теперь, если кто-нибудь может помочь в выводе, сохранить первые 2 столбца для каждого сервера и различные значения столбцов 3,4 для новых столбцов (5,6). Также было бы хорошо, если бы я тоже получал титулы. Например:

Служба сервера перед состоянием до режима после состояния после режима BL3C4V     wudfsvc Остановлено Авто Остановлено вручную
D7MCYP AdobeARMservice Запуск Авто Остановлено Авто     

1 ответ

Решение

Примечание. Приведенный ниже код является упражнением в разборе текстовых данных на объекты для более надежной и гибкой обработки.
В идеале, однако, обработка должна начинаться с объектов, а не с простого текста, поэтому начинаем с командлетов PowerShell, таких как Get-Service а не вывод текста из внешних утилит предпочтительнее.

Предполагая, что все записи в каждом входном файле имеют соответствующую запись server + service-name в соответствующем другом файле:

$f1, $f2 = "c:\temp\mek\123-first.txt", "c:\temp\mek\123-second.txt"
Compare-Object (Get-Content $f1) (Get-Content $f2) | ForEach-Object {
    $i = 0; $ht = @{}; $vals = -split $_.InputObject
    foreach($col in 'Server', 'Service', 'State', 'Mode') {
      $ht.$col = $vals[$i++]
    }
    $ht.Before = $_.SideIndicator -eq '<='
    [pscustomobject] $ht
  } | Group-Object Server, Service | ForEach-Object {
      $ndxBefore, $ndxAfter = if ($_.Before) { 0, 1 } else { 1, 0 }
      [pscustomobject] @{
        Server = $_.Group[0].Server
        Service = $_.Group[0].Service
        'State Before' = $_.Group[$ndxBefore].State
        'Mode Before' = $_.Group[$ndxBefore].Mode
        'State After' = $_.Group[$ndxAfter].State
        'Mode After' = $_.Group[$ndxAfter].Mode
      }
    } | Sort-Object Server, Service |
      Format-Table

Замечания:

  • Выше форматирует вывод для отображения (используя Format-Table), не отправляя его в файл.
    Вы можете добавить | Out-File "c:\temp\mek\results.txt" сохранить то же представление в файл.

  • Однако учтите, что команда - раньше Format-Table применяется - возвращает объекты с индивидуальными свойствами, поэтому вы можете выводить в файл в различных форматах, например, используя Export-Csv, например.

Пример вывода:

Server Service                   State Before Mode Before State After Mode After
------ -------                   ------------ ----------- ----------- ----------
D7MCYP AdobeFlashPlayerUpdateSvc Stopped      Manual      Stopped     Auto      
D7MCYP AeLookupSvc               Stopped      Manual      Started     Manual    

Пояснение:

Используется один длинный конвейер, что делает код лаконичным и эффективным для памяти.
Трубопровод ломается следующим образом:

  • Сравнение:

    • Compare-Object сравнивает массив строк из двух входных файлов, возвращаемых Get-Content звонки и выходы [pscustomobject] экземпляры, представляющие найденные различия, со строковым свойством .SideIndicator указание, находится ли линия под рукой (доступно через .InputObject) является уникальным для LHS (1-й входной файл) - <= - или RHS (2-й входной файл) - >=
  • Преобразование в пользовательские объекты:

    • Блок скрипта ({ ... }) перешел к ForEach-Object выполняется для каждого входного объекта (представлен как $_).

    • -split $_.InputObject разбивает имеющуюся "разностную линию" на поля с помощью пробелов и сохраняет полученные поля в виде массива в $vals,

    • $ht является вспомогательной хэш-таблицей, которая используется для сопоставления значений полей с именами полей.

    • $ht.Before добавляет булеву запись, чтобы указать, является ли линия разницы от "до файла" (1-й входной файл) или нет.

    • [pscustomobject] $ht преобразует aux. hashtable в пользовательский объект и выводит его (отправляет через конвейер).

  • Группировка:

    • Group-Object используется для группировки результирующих объектов может быть общим Server а также Service значения свойств, в результате чего [Microsoft.PowerShell.Commands.GroupInfo] экземпляр, представляющий каждую группу.
  • Преобразование в комбинированные пользовательские объекты:

    • Снова, ForEach-Object используется для выполнения обработки объекта ввода.

    • [pscustomobject] @{ ... } используется для создания каждого комбинированного выходного объекта, снова используя вспомогательную хэш-таблицу.

    • $_.Group содержит входные объекты, которые формируют каждую группу - в нашем случае, $_.Group[0] а также $_.Group[1] это строки ввода, преобразованные в объекты, представляющие данную комбинацию сервер-сервис.

    • По определению оба входных объекта имеют одинаковые .Server а также .Service значения, так что вслепую $_.Group[0] Значения для объединенного объекта вывода будут делать.

    • В отличие от * Before а также * After Свойства соответствующего входного объекта (из 1-го или 2-го файла), поэтому индексы массива $ndxBefore а также $ndxAfter выбираются соответственно через ранее добавленные .Before имущество

  • Сортировка:

    • Sort-Object сортирует результирующие объекты по указанным свойствам.
  • Форматирование вывода:

    • Командлет форматирования вывода Format-Table обеспечивает сортировку объектов в виде таблицы.
Другие вопросы по тегам