【问题标题】:Do Powershell conditional operators support search in arrays of object?Powershell 条件运算符是否支持在对象数组中搜索?
【发布时间】:2019-06-17 07:35:45
【问题描述】:

我需要通过 -in-contain 运算符检查对象数组是否包含特定对象,但没有运气,例如:

PS C:\> ($3_devices = Get-MobileDevice -ResultSize 3).guid

Guid                                
----                                
25c2f857-0098-46c3-b965-f22008006d16
1cc13103-3b36-4b69-ab51-b7e381453326
aae35123-4695-40b4-b6e5-7ea6cd0713c2


PS C:\> ($1_device = Get-MobileDevice -Resultsize 2 | select -last 1).guid

Guid                                
----                                
1cc13103-3b36-4b69-ab51-b7e381453326

PS C:\> $1_device -in $3_devices
False

PS C:\> $3_devices -contains $1_device
False

PS C:\> $3_devices.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------  
True     True     Object[]                                 System.Array


PS C:\> $1_device.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     PSObject                                 System.Object

哪里出了错,还是 PS 条件运算符支持对象?

谢谢。

【问题讨论】:

  • 试试$3_devices.guid -contains $1_device.guid
  • Gert,它可以工作,但我需要比较整个对象或使用 several -and 运算符通过几个参数比较对象。但是使用大量的 -and 似乎有些过分了。所以,我想使用 -in-contains 或了解它为什么不起作用。谢谢。
  • 如果你想通过引用进行比较,你可以做$3_devices -contains $1_device(如果它们实际上是同一个对象)。如果您想要通过特定参数进行“自定义”比较,当然您必须自己编写。但我们甚至不知道您的对象是什么样的。
  • @ДенисКвочка 我假设 guid 是设备的唯一标识符。如果是的话,你不需要更多的比较。
  • @marsze,它不起作用,请看上面给出的例子。在我的示例中,“我的对象”是 Exchange Online 中的移动设备。因此,它们不是自定义对象。

标签: arrays powershell object conditional-operator


【解决方案1】:

“包含”仅在满足以下条件之一时适用于对象数组:

1) 该数组包含使用 IComparable 和/或 IEquatable 接口实现的类型的对象。 Lee Holmes 有一个很棒的blog post about this.

示例:从 Get-Service 返回的对象类型 [System.ServiceProcess.ServiceController] 没有这些接口之一,因此即使对象看起来相同,“-contains”也不起作用:

$services = Get-Service
$service  = Get-Service -Name 'Spooler'

$service.GetType().GetInterfaces()

IsPublic IsSerial Name                                     BaseType                                                                                                                 
-------- -------- ----                                     --------                                                                                                                 
True     False    IComponent                                                                                                                                                        
True     False    IDisposable        

$services -contains $service
False                                 

2) 您的比较对象有reference equality 和数组中的一个对象——它们实际上存储在内存中的相同位置。

在您的示例中,您使用两个不同的命令检索数组和比较对象,导致重复对象存储在内存中的不同位置。如果您将数组中的比较对象分配给一个新变量(默认为by reference)并与之进行比较,它应该可以工作:

$services = Get-Service
$service  = $services[0]

$service.GetType().IsValueType
False

$services -contains $service
True

虽然这不是特别有用的解决方案。

我的建议:如果您想通过多个属性而不是所有属性来匹配两个不同的引用对象,这里有一个不使用多个“-and”条件的简洁、快速的解决方案:

$services = Get-Service

$serviceToMatch = Get-Service -Name 'Spooler' | Select -First 1

$propertiesToMatch = @('Status','StartType')

$propertiesToMatch | ForEach { $services = $services.Where({$_.$Input -eq $serviceToMatch.$Input}) }

$services | Select Name, Status, StartType | Sort Name

这会生成与“Spooler”服务匹配的“Status”和“StartType”的服务列表。

或者,您可以创建一个自定义的属性名称哈希表来匹配:

$services = Get-Service

$serviceToMatch = @{
    Status    = 'Stopped'
    StartType = 'Automatic'
}

$serviceToMatch.Keys | ForEach { $services = $services.Where({$_.$Input -eq $serviceToMatch.$Input}) }

$services | Select Name, Status, StartType | Sort Name

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 2011-08-27
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2012-02-11
    相关资源
    最近更新 更多