如何过滤Powershell中来自控制台程序的行?

时间:2019-04-08 08:25:29

标签: powershell powershell-v5.0

我有一个.exe控制台程序,该程序以以下格式将结果放入控制台:

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

我想在PowerShell脚本中进行选择,并按CompanyName进行过滤。

我尝试过:

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

但是看来这行不通。

2 个答案:

答案 0 :(得分:3)

这是将EXE输出转换为对象的Powershell集合的一种方法。它做什么...

  • 为您的exe文件的输出创建伪造的版本
  • 过滤掉重复的连字符
  • 什么都没有替换领先空间
  • 用逗号替换2个或多个空格
  • 将类似于CSV的字符串数组转换为Powershell对象的集合

这是代码[ grin ] ...

# 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  

答案 1 :(得分:1)

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的输出成为 array ,即使它恰好输出 one < / em>行,这样-match在该数组上执行 filtering (使用标量LHS,-match返回 Boolean )。

  • 正则表达式^\s+test1\s在每一行(+)的开头匹配一个或多个(\s)空格字符(^),后跟文字{ {1}},后跟一个空格字符-从而限制了与test1列的匹配。

如果要将结果解析为单个字段:

CompanyName

Lee Dailey's answer

  • 向您展示如何将外部程序的输出解析为自定义对象,您可以查询其属性,方法是先将程序的输出转换为CSV文本,然后通过# 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 将其解析为自定义对象。

    • 虽然这在PowerShell的精神上非常重要,但您不可避免地要付出性能损失,并且对于提取简单的子字符串可能不值得。
  • 然后,令人遗憾的是,放弃了将输入解析为 objects 的优势,方法是恢复为字符串匹配,从而消除了可以进行属性个体匹配的优势:

    • ConvertFrom-Csv(一个 string 运算符)应用于自定义对象 LHS会产生类似于哈希表的 表示形式对于显示不适合编程处理的显示;例如:
      -match

    • 因此-概括地说-使用@{CompanyName=test1; CompanyId=1; CompanyType=Root}可能会导致误报-因为匹配不限于感兴趣的属性。

      < / li>

简而言之:如果您遇到将输入解析为 object 的麻烦-如果有必要的话-使用它们的 properties 进行健壮的过滤,就像您尝试的那样问题:

  • -match
  • 或更简洁地说,使用PSv3 +语法:
    $CompanyInfo | where {$_.CompanyName -eq 'test1'}
  • 或更有效地在PSv4 +中,使用$CompanyInfo | where CompanyName -eq test1 array方法
    .Where()