Как отфильтровать строки в powershell, взятые из консольной программы?

У меня есть консольная программа .exe, которая выводит результат в консоль в следующем формате:

 ------------------ ----------- ----------------
  CompanyName        CompanyId   CompanyType
 ------------------ ----------- ----------------
  test1              1           Root
  test2              2           Center
  test3              3           Company
 ------------------ ----------- ----------------

Я хотел бы получить это в сценарии PowerShell и отфильтровать по CompanyName.

Я пробовал это с:

MyTool.exe companies | where {$_.CompanyName -eq 'test1'}

но кажется, что это не работает.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
86
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот один из способов преобразовать вывод EXE в набор объектов powershell. что оно делает ...

  • создает фальшивую версию вывода вашего исполняемого файла
  • отфильтровывает строки с повторяющимися дефисами
  • заменяет ведущие пробелы ничем
  • заменяет 2 или более пробелов запятой
  • преобразует этот CSV-подобный массив строк в коллекцию объектов powershell

вот код [ухмылка] ...

# fake getting string output from an EXE
$InStuff = @'
 ------------------ ----------- ----------------
  CompanyName        CompanyId   CompanyType
 ------------------ ----------- ----------------
  test1              1           Root
  test2              2           Center
  test3              3           Company
 ------------------ ----------- ----------------
'@ -split [environment]::NewLine

$CompanyInfo = $InStuff -notmatch '--{2,}' -replace '^ {1,}' -replace ' {2,}', ',' |
    ConvertFrom-Csv

$CompanyInfo
'=' * 30
$CompanyInfo -match 'Test1'

выход ...

CompanyName CompanyId CompanyType
----------- --------- -----------
test1       1         Root       
test2       2         Center     
test3       3         Company    
==============================
test1       1         Root  

-trim ' ' вместо -replace '^ {1,}' (что равно -replace '^ +') также удалит возможные конечные пробелы. Вы можете написать '--{2,}' как '-{3,}' (+1)

user6811411 08.04.2019 12:54

Хорошо сделано, хотя $CompanyInfo -match 'Test1' одновременно неясно и хрупко (вы сопоставляете строковое представление пользовательского объекта только для человеческого глаза). Учитывая, что вы уже разобрали все на объекты, используйте подход фильтрации OP: $CompanyInfo | where CompanyName -eq test1

mklement0 08.04.2019 12:57

@LotPings - как вы думаете, я должен изменить свой ответ? я согласен, что ваши тесты более надежны, а также несколько проще/очевиднее. [краснеть]

Lee_Dailey 08.04.2019 21:35

@ mklement0 - мне кажется, это не так уж неясно. [ухмылка] OP, скорее всего, будет использовать то, что у них уже есть, но метод, который я показываю, был достаточно надежным и может быть немного быстрее с большими наборами данных.

Lee_Dailey 08.04.2019 21:37

@Lee_Dailey: Пожалуйста, смотрите мой ответ (нижняя часть).

mklement0 08.04.2019 22:11

@mklement0 - очень хорошее объяснение вашей точки зрения! спасибо ... .Where() - это действительно быстрый способ добраться туда - один из моих любимых способов использования. [ухмылка]

Lee_Dailey 08.04.2019 22:32

PowerShell сообщает о выходе внешней программы как массив строк (строки).

Чтобы отфильтровать такой вывод с помощью синтаксического анализа строки, используйте оператор -match:

# Extract the line of interest with -match and a regex
PS> @(MyTool.exe companies) -match '^\s+test1\s'
test1              1           Root

Примечание:

  • @(...), хотя здесь это и не является строго необходимым, гарантирует, что вывод MyTool.exe станет множество, даже если он выводит только строку один, так что -match выполняет фильтрация для этого массива (со скалярным LHS, -match возвращает логический).

  • Регулярное выражение ^\s+test1\s соответствует одному или нескольким (+) символам пробела (\s) в начале каждой строки (^), за которыми следует литерал test1, за которым следует символ пробела, тем самым ограничивая соответствие столбцу CompanyName.

Если вы хотите разобрать результат на отдельные поля:

# Extract the line of interest with -match and a regex, 
# then split that line into whitespace-separated tokens and store
# them in individual variables.
PS> $name, $id, $type = -split (@(MyTool.exe companies) -match '^\s+test1\s')
PS> $name, $id, $type  
test1
1
Root

Ответ Ли Дэйли:

  • показывает вам, как вместо этого анализировать вывод вашей внешней программы в пользовательские объекты, чей свойства, которые вы можете запросить, сначала преобразуя вывод вашей программы в текст CSV, а затем анализируя его в пользовательские объекты с помощью ConvertFrom-Csv.

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

    • применение -match — оператора нить — к LHS пользовательский объект приводит к представлению отображать в виде хеш-таблицы-подобно, которое нет подходит для программной обработки; например:
      @{CompanyName=test1; CompanyId=1; CompanyType=Root}

    • следовательно, говоря абстрактно, использование -match может привести к ложные срабатывания, потому что сопоставление не ограничивается интересующим свойством.

Вкратце: если вы столкнулись с трудностями анализа ввода в объекты - если это вообще необходимо - используйте их характеристики для надежной фильтрации, как вы пытались в своем вопросе:

  • $CompanyInfo | where {$_.CompanyName -eq 'test1'}
  • или, более кратко, используя синтаксис PSv3+:
    $CompanyInfo | where CompanyName -eq test1
  • или, что более эффективно, в PSv4+, используя .Where()метод массива:
    $CompanyInfo.Where({ $_.CompanyName -eq 'test1'})

Другие вопросы по теме