У меня есть консольная программа .exe
, которая выводит результат в консоль в следующем формате:
------------------ ----------- ----------------
CompanyName CompanyId CompanyType
------------------ ----------- ----------------
test1 1 Root
test2 2 Center
test3 3 Company
------------------ ----------- ----------------
Я хотел бы получить это в сценарии PowerShell и отфильтровать по CompanyName
.
Я пробовал это с:
MyTool.exe companies | where {$_.CompanyName -eq 'test1'}
но кажется, что это не работает.
Вот один из способов преобразовать вывод EXE в набор объектов 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
Хорошо сделано, хотя $CompanyInfo -match 'Test1'
одновременно неясно и хрупко (вы сопоставляете строковое представление пользовательского объекта только для человеческого глаза). Учитывая, что вы уже разобрали все на объекты, используйте подход фильтрации OP: $CompanyInfo | where CompanyName -eq test1
@LotPings - как вы думаете, я должен изменить свой ответ? я согласен, что ваши тесты более надежны, а также несколько проще/очевиднее. [краснеть]
@ mklement0 - мне кажется, это не так уж неясно. [ухмылка] OP, скорее всего, будет использовать то, что у них уже есть, но метод, который я показываю, был достаточно надежным и может быть немного быстрее с большими наборами данных.
@Lee_Dailey: Пожалуйста, смотрите мой ответ (нижняя часть).
@mklement0 - очень хорошее объяснение вашей точки зрения! спасибо ... .Where()
- это действительно быстрый способ добраться туда - один из моих любимых способов использования. [ухмылка]
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
.
затем, к сожалению, отказывается от преимуществ анализа ввода в объекты, возвращаясь к сопоставлению строк, которое сводит на нет преимущества наличия в распоряжении сопоставления отдельных свойств:
применение -match
— оператора нить — к LHS пользовательский объект приводит к представлению отображать в виде хеш-таблицы-подобно, которое нет подходит для программной обработки; например: @{CompanyName=test1; CompanyId=1; CompanyType=Root}
следовательно, говоря абстрактно, использование -match
может привести к ложные срабатывания, потому что сопоставление не ограничивается интересующим свойством.
Вкратце: если вы столкнулись с трудностями анализа ввода в объекты - если это вообще необходимо - используйте их характеристики для надежной фильтрации, как вы пытались в своем вопросе:
$CompanyInfo | where {$_.CompanyName -eq 'test1'}
$CompanyInfo | where CompanyName -eq test1
.Where()
метод массива:$CompanyInfo.Where({ $_.CompanyName -eq 'test1'})
-trim ' '
вместо-replace '^ {1,}'
(что равно-replace '^ +'
) также удалит возможные конечные пробелы. Вы можете написать'--{2,}'
как'-{3,}'
(+1)