当输出包含@{<value1=xxx>,<value1=yyy> } 时如何展开多个属性?

问题描述

我知道有很多关于扩展单个属性的帖子,希望这是一个简单的帖子,但由于 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
,

补充Theo's helpful answer

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 更改为对丰富的显示格式表示进行操作。
  • 此外,如果您确实Select-String 对此类对象进行操作,其输出Microsoft.PowerShell.Commands.MatchInfo 实例)将不再包含输入对象,只有它们的字符串表示,这意味着为了提取值VolkswagenPassat,你必须执行字符串解析,既麻烦又不健壮。


要根据属性值过滤具有属性的输入对象,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