Powershell 如何从另一个变量中减去一个变量,两者都包含 Exchange 邮箱对象标识

Powershell how to subtract a variable from another variable, both contain the Exchange Mailbox Object Identity

我有两个变量,它们都包含用户帐户的 Get-Mailbox 对象 "Identity"。我需要从另一个 IE 中减去一个的内容:

$termednofwd = (domain.local/OUname/SubOU/Users/first1 last1, domain.local/OUname/SubOU/first2 last2)

$termedfmr = (domain.local/OUname/SubOU/Users/first1 last1)

我想要一些东西,可以从 $termednofwd 中减去 $termedfmr 的内容,给出如下所示的内容。 Compare-Object 只列出两者的内容,我基本上需要从第一个变量中减去两者的内容。 本质上: $termednofwdnofmr = $termednofwd - $termedfmr 结果是:

$termednofwdnofmr = (domain.local/OUname/SubOU/first2 last2)

在集合论术语中,您正在寻找两个集合之间的相对补充Compare-Object 可以提供,尽管它需要额外的努力:

默认情况下,Compare-Object提供两个集合之间的对称差异,即它列出了相对互补的联合;也就是说,给定两个集合 A 和 B,它列出了 both B 中不存在于 A 中的那些元素 and 那些 A 中不存在于 B 中的元素,它使用 .SideIndicator 属性 来表示哪个是哪个:

  • '<=' 表示集合 A 唯一的对象(-ReferenceObject 参数,或第一个 positional 参数),而
  • '=>' 表示集合 B 唯一的元素(-DifferenceObject 参数,或第二个位置参数)。

因此,您需要按 .SideIndicator 值过滤输出对象。
-PassThru 开关还确保输入对象被传递(而不是将它们包装在 .InputObject 包含它们的 [pscustomobject] 实例中):

$termednofwd = 'domain.local/OUname/SubOU/Users/first1 last1',
               'domain.local/OUname/SubOU/first2 last2'

$termedfmr = 'domain.local/OUname/SubOU/Users/first1 last1'

# Return the elements in $termednofwd that aren't also present in $termedfmr
Compare-Object $termednofwd $termedfmr -PassThru |
  Where-Object SideIndicator -eq '<='

以上结果 'domain.local/OUname/SubOU/first2 last2',即 $termednofwd 中不存在于 $termedfmr 中的那些元素。

注意:为简洁起见,以上使用strings作为输入对象;在您的情况下,由于您正在使用 Get-Mailbox cmdlet 返回的对象并希望根据它们的 .Identity 属性 值进行比较,因此您需要使用:

# If you only need the identity values as results.
Compare-Object $termednofwd.Identity $termedfmr.Identity -PassThru |
  Where-Object SideIndicator -eq '<='

# Alternatively, if you need the whole mailbox objects.
Compare-Object -Property Identity $termednofwd $termedfmr -PassThru |
  Where-Object SideIndicator -eq '<='

另请参阅:GitHub issue #4316,它建议使用 集合操作 .

增强 Compare-Object

所以这本质上是集合论的一个实际例子,即我想要集合 1 中不在集合 2 中的所有项目。PowerShell 没有直接的命令行开关来做到这一点,但通过 . Net,您可以利用 Microsoft Linq 库为您完成这项工作。

唯一的技巧是您需要将 PowerShell 变量转换为对象数组才能使函数调用正常工作:

$results = [System.Linq.Enumerable]::Except([object[]]$mainArray, [object[]]$subArray)

最后,您在两个数组中比较的项目必须具有可比性。对于像字符串这样的简单事物,这总是有效的。如果你比较的是比较复杂的对象,可能不能直接比较。