如何过滤从控制台程序中获取的 powershell 中的行?
How to filter rows in the powershell which are taken from console program?
我有一个 .exe
控制台程序,它以下列格式将结果放入控制台:
------------------ ----------- ----------------
CompanyName CompanyId CompanyType
------------------ ----------- ----------------
test1 1 Root
test2 2 Center
test3 3 Company
------------------ ----------- ----------------
我想在 PowerShell 脚本中获取它并按 CompanyName
.
过滤
我试过:
MyTool.exe companies | where {$_.CompanyName -eq 'test1'}
不过好像不行。
这是将 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
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 行,以便 -match
在该数组上执行 filtering (使用标量 LHS,-match
returns一个布尔值).
正则表达式 ^\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 的精神,但您不可避免地要付出性能代价,而且对于提取简单的子字符串来说,这样做可能不值得。
然后,遗憾的是,放弃了将输入解析为 objects 的优势,恢复为字符串匹配,这否定了具有 属性 的优势-个性化匹配:
应用-match
- 字符串 运算符 - 到自定义对象 LHS 生成哈希表- like 表示 display not 适合程序化处理;例如:
@{CompanyName=test1; CompanyId=1; CompanyType=Root}
因此 - 抽象地说 - 使用 -match
会导致 误报 - 因为匹配不限于 属性 感兴趣。
简而言之:如果您不厌其烦地将输入解析为 objects - 如果有必要 - 使用它们的 properties强大的过滤,正如您在问题中尝试的那样:
$CompanyInfo | where {$_.CompanyName -eq 'test1'}
- 或者,更简洁地说,使用 PSv3+ 语法:
$CompanyInfo | where CompanyName -eq test1
- 或者,更有效地,在 PSv4+ 中,使用
.Where()
数组方法:
$CompanyInfo.Where({ $_.CompanyName -eq 'test1'})
我有一个 .exe
控制台程序,它以下列格式将结果放入控制台:
------------------ ----------- ----------------
CompanyName CompanyId CompanyType
------------------ ----------- ----------------
test1 1 Root
test2 2 Center
test3 3 Company
------------------ ----------- ----------------
我想在 PowerShell 脚本中获取它并按 CompanyName
.
我试过:
MyTool.exe companies | where {$_.CompanyName -eq 'test1'}
不过好像不行。
这是将 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
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 行,以便-match
在该数组上执行 filtering (使用标量 LHS,-match
returns一个布尔值).正则表达式
^\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 的精神,但您不可避免地要付出性能代价,而且对于提取简单的子字符串来说,这样做可能不值得。
然后,遗憾的是,放弃了将输入解析为 objects 的优势,恢复为字符串匹配,这否定了具有 属性 的优势-个性化匹配:
应用
-match
- 字符串 运算符 - 到自定义对象 LHS 生成哈希表- like 表示 display not 适合程序化处理;例如:@{CompanyName=test1; CompanyId=1; CompanyType=Root}
因此 - 抽象地说 - 使用
-match
会导致 误报 - 因为匹配不限于 属性 感兴趣。
简而言之:如果您不厌其烦地将输入解析为 objects - 如果有必要 - 使用它们的 properties强大的过滤,正如您在问题中尝试的那样:
$CompanyInfo | where {$_.CompanyName -eq 'test1'}
- 或者,更简洁地说,使用 PSv3+ 语法:
$CompanyInfo | where CompanyName -eq test1
- 或者,更有效地,在 PSv4+ 中,使用
.Where()
数组方法:
$CompanyInfo.Where({ $_.CompanyName -eq 'test1'})