问题描述
我知道有很多关于扩展单个属性的帖子,希望这是一个简单的帖子,但由于 select-string -simplematch,我的输出看起来像这样
@{品牌=大众;型号=帕萨特}
@{品牌=福特;型号=蒙迪欧}
大众、帕萨特
福特、蒙迪欧
当我选择对象时 * 我得到以下但我似乎无法得到值
忽略大小写:真
行号:1
行:@{品牌=大众;型号=帕萨特}
文件名:输入流
路径:输入流
图案:@{品牌=大众;型号=帕萨特}
上下文:
匹配:{}}
忽略大小写:真
行号:2
行:@{品牌=福特;型号=蒙迪欧}
文件名:输入流
路径:输入流
模式:@{品牌=福特;型号=蒙迪欧}
上下文:
匹配:{}}
解决方法
不要对 PsObject 的集合执行 select-string
,因为该 cmdlet 是为在字符串和文件中查找文本而设计的..Select-Object -ExpandProperty
允许您扩展一个属性,而不是全部。
如果您想要这样的输出,请遍历数组中的对象并按照您希望的方式将它们组合成一个字符串。
假设你的数组是这样的:
$theCarCollection = [PsCustomObject]@{Brand='Volkswagen'; Model='Passat'},[PsCustomObject]@{Brand='Ford'; Model='Mondeo'}
然后通过循环对象并选择您需要的属性来格式化输出
($theCarCollection | ForEach-Object { '{0},{1}' -f $_.Brand,$_.Model }) -join [environment]::NewLine
将输出:
Volkswagen,Passat
Ford,Mondeo
,
这可能是谎言:
Select-String -Path "C:\temp\test.txt" -Pattern "test" | select line -ExpandProperty line
,
tl;dr:
# Note the use of -PipelineVariable obj and the use of $obj later.
PS> Write-Output -PipelineVariable obj (
[pscustomobject] @{ Brand = 'Volkswagen'; Model = 'Passat' },[pscustomobject] @{ Brand = 'Ford'; Model = 'Mondeo' }
) |
Select-String -SimpleMatch wagen |
ForEach-Object { $obj.psobject.Properties.Value -join ',' }
Volkswagen,Passat
Write-Output
命令只是为代码中的 Select-String
生成输入对象的实际命令的替代,例如 Import-Csv
。
-
您的
Select-String
输出意味着[pscustomobject]
实例作为其输入,例如Import-Csv
的输出。- 例如,您的输出意味着一个输入对象,例如
[pscustomobject] @{ Brand = 'Volkswagen'; Model = 'Passat' }
- 例如,您的输出意味着一个输入对象,例如
-
正如 Theo 所指出的,
Select-String
旨在对 字符串 进行操作,而不是对具有属性的 对象 进行操作。-
当
Select-String
收到这样的对象时,它会为它们创建一个字符串表示并搜索那个。 -
特别没有帮助的是,这个字符串表示与您在终端(控制台)中看到的不同,PowerShell的丰富输出格式是用过的;相反,执行简单的
.ToString()
字符串化,它使用[pscustomobject]
实例导致诸如'@{Brand=Volkswagen; Model=Passat}'
之类的表示(可能令人困惑,这类似于 - 但与 - 哈希表文字不同).-
GitHub issue #10726 建议将
Select-String
更改为对丰富的显示格式表示进行操作。
-
GitHub issue #10726 建议将
-
-
此外,如果您确实让
Select-String
对此类对象进行操作,其输出(Microsoft.PowerShell.Commands.MatchInfo
实例)将不再包含输入对象,只有它们的字符串表示,这意味着为了提取值Volkswagen
和Passat
,你必须执行字符串解析,既麻烦又不健壮。
要根据属性值过滤具有属性的输入对象,Where-Object
是更好的选择;例如:
PS> [pscustomobject] @{ Brand = 'Volkswagen'; Model = 'Passat' },[pscustomobject] @{ Brand = 'Ford'; Model = 'Mondeo' } |
Where-Object Brand -eq Volkswagen
Brand Model
----- -----
Volkswagen Passat
也就是说,如果您不知道输入对象具有哪些属性,并且想在某处定位一个值,那么使用 Select-Object
仍然很有帮助在对象中,通过它的字符串表示:
PS> [pscustomobject] @{ Brand = 'Volkswagen'; Model = 'Passat' },[pscustomobject] @{ Brand = 'Ford'; Model = 'Mondeo' } |
Select-String -SimpleMatch wagen
@{Brand=Volkswagen; Model=Passat}
以上是您尝试过的,但是,如上所述,这有效地仅输出整个对象的字符串表示,之后没有(容易)提取属性值的能力。
解决方案是在 input-object-production 命令上使用 common -PipelineVariable
parameter,它允许在 later 管道段的 (ForEach-Object
) 中访问手头的对象脚本块,它允许您轻松创建所需的以逗号分隔的属性值列表(即使不知道属性名称):
# Note the use of -PipelineVariable obj and the use of $obj later.
PS> Write-Output -PipelineVariable obj (
[pscustomobject] @{ Brand = 'Volkswagen'; Model = 'Passat' },Passat
$obj.psobject.Properties.Value
使用 PowerShell 为所有对象提供的隐藏的、内在的 .psobject
属性,这是反射的丰富来源,在这种情况下可以轻松访问所有属性值,通过 member enumeration。