Powershell 如何在对象中搜索值?

Powershell 如何在对象中搜索值?,powershell,object,properties,powershell-v5.1,Powershell,Object,Properties,Powershell V5.1,假设你有一个巨大的对象,它可能有也可能没有嵌套的数组/对象 # Assuming 'user1' exists in the current domain $obj = Get-ADUser 'user1' -Properties * 我想在该对象中搜索字符串SMTP大小写不敏感 我尝试的 $obj | Select-String "SMTP" 但它不起作用,因为匹配项位于嵌套集合中。。。简而言之,它位于属性$obj.proxyAddresses中 如果我运行$obj.proxyAd

假设你有一个巨大的对象,它可能有也可能没有嵌套的数组/对象

# Assuming 'user1' exists in the current domain    
$obj = Get-ADUser 'user1' -Properties *
我想在该对象中搜索字符串
SMTP
大小写不敏感

我尝试的

$obj | Select-String "SMTP"
但它不起作用,因为匹配项位于嵌套集合中。。。简而言之,它位于属性
$obj.proxyAddresses

如果我运行
$obj.proxyAddress.GetType()
,它将返回:

IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False ADPropertyValueCollection System.Collections.CollectionBase IsPublic IsSerial名称基类型 -------- -------- ---- -------- True False ADPropertyValueCollection System.Collections.CollectionBase 最好的办法是什么?我知道您可以使用通配符匹配或
.Contains()
,通过属性循环并手动查找它,但我更喜欢内置解决方案

因此,对于对象,而不仅仅是字符串,它将是一个
grep

注意:此答案包含背景信息,并提供了一种快速且不需要自定义功能的方法
有关基于通过自定义函数进行反射的更全面、系统的方法,请参见。

Select String
对字符串进行操作,当它将不同类型的输入对象强制为字符串时,它本质上会对其调用
.ToString()
,这通常会产生泛型表示,例如仅是类型名,通常不会枚举属性。
请注意,对象的
.ToString()
表示与PowerShell到控制台的默认输出不同,后者更丰富

如果要查找的全部内容是在对象的显示字符串表示形式中查找子字符串,则可以通过管道输送到
输出字符串-流
,然后再通过管道输送到
选择字符串

$obj | Out-String -Stream | Select-String "SMTP"
Out String
创建一个字符串表示形式,该表示形式与默认情况下呈现给控制台的表示形式相同(它使用PowerShell的输出格式系统);添加
-Stream
会逐行发出该表示,而默认情况下会发出一个多行字符串

当然,只有当for display表示法实际显示感兴趣的数据时,此方法才有效-请参见下面的注意事项

注意事项

  • 如果格式化的表示形式恰好是表格形式,并且您的搜索字符串是属性名,则感兴趣的值可能位于下一行

    • 您可以通过强制列表样式显示来解决此问题,其中每个属性都占用自己的一行(名称和值)如下所示:

      $obj | Format-List | Out-String -Stream | Select-String "SMTP"
      
    • 如果预期多行属性值,则可以使用
      选择字符串的
      -Context
      参数来包括围绕匹配的行,例如
      -Context 0,1
      ,以便在匹配后也输出该行

    • 如果知道感兴趣的值位于集合值属性中,则可以使用
      $FormatEnumerationLimit=-1
      强制列出所有元素(默认情况下,仅显示前4个元素)

      • 警告:自PowerShell Core 6.1.0起,
        $FormatEnumerationLimit
        仅在全局范围内设置时有效-请参阅
      • 但是,一旦您需要设置偏好变量<代码> $FruttRealErrimeLimest,现在是考虑基于.< /LI>中自定义函数的更彻底的解决方案的时候了。
  • 值在表示中可能会被截断,因为
    Out String
    假定固定的线宽;您可以使用
    -Width
    来更改该值,但请小心使用大数字,因为表格表示会使用每个输出行的全宽度

注意:此答案包含背景信息,并提供了一种不需要自定义功能的快速而肮脏的方法
有关基于通过自定义函数进行反射的更全面、系统的方法,请参见。

Select String
对字符串进行操作,当它将不同类型的输入对象强制为字符串时,它本质上会对其调用
.ToString()
,这通常会产生泛型表示,例如仅是类型名,通常不会枚举属性。
请注意,对象的
.ToString()
表示与PowerShell到控制台的默认输出不同,后者更丰富

如果要查找的全部内容是在对象的显示字符串表示形式中查找子字符串,则可以通过管道输送到
输出字符串-流
,然后再通过管道输送到
选择字符串

$obj | Out-String -Stream | Select-String "SMTP"
Out String
创建一个字符串表示形式,该表示形式与默认情况下呈现给控制台的表示形式相同(它使用PowerShell的输出格式系统);添加
-Stream
会逐行发出该表示,而默认情况下会发出一个多行字符串

当然,只有当for display表示法实际显示感兴趣的数据时,此方法才有效-请参见下面的注意事项

注意事项

  • 如果格式化的表示形式恰好是表格形式,并且您的搜索字符串是属性名,则感兴趣的值可能位于下一行

    • 您可以通过强制列表样式显示来解决此问题,其中每个属性都占用自己的一行(名称和值)如下所示:

      $obj | Format-List | Out-String -Stream | Select-String "SMTP"
      
    • 如果您预期多行属性值,则可以使用
      选择字符串的
      -Context
      参数来包括围绕匹配项的行,例如
      -Context 0,1
      ,也可以在ma之后输出行
      if (($Depth -gt 0)  -and -not ($InputObject.GetType().IsPrimitive -or ($InputObject -is 'System.String'))) {
          [string[]]$members = Get-Member -InputObject $InputObject -MemberType $PropertyTypesToSearch | Select-Object -ExpandProperty Name
          ForEach ($member in $members) {
              $InputObject."$member" | Where-Object {$_ -ne $null} | Find-ValueMatchingCondition -Condition $Condition -Depth ($Depth - 1) -Name $member | ForEach-Object {$_.Name = ('{0}.{1}' -f $Name, $_.Name);$_}
          }
      }