Powershell как вычесть переменную из другой переменной, обе содержат идентификатор объекта почтового ящика Exchange

#powershell #set #exchange-server

Вопрос:

У меня есть две переменные, обе из которых содержат Get-Mailbox объект "Identity" учетных записей пользователей. Мне нужно вычесть содержимое одного из другого, Т. Е.:

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

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

Мне нужно что — то, что вычитало бы содержимое $termedfmr из $termednofwd приведенного ниже. Compare-Object только перечисляет содержимое, которое есть в обоих, мне в основном нужно вычесть то, что есть в обоих, из первой переменной.
по существу:
$termednofwdnofmr = $termednofwd - $termedfmr в результате этого:

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

Комментарии:

1. Пожалуйста, сначала подумайте о чем-то вроде замены текста с помощью PowerShell . Во всем опубликованном вами коде есть проблемы с синтаксисом, поэтому это добавляет путаницы.

Ответ №1:

В терминах теории множеств вы ищете относительное дополнение между двумя коллекциями, которое Compare-Object может обеспечить, хотя и требует дополнительных усилий:

По умолчанию Compare-Object предоставляет симметрическая разность двух множеств, т. е. он перечисляет Союза относительной дополняет; то есть, учитывая два набора A и B, в нем содержатся обе эти элементы не присутствуют в и те элементы, не присутствующие в B, и он использует .SideIndicator свойство, чтобы указать, что есть что:

  • '<=' указывает объекты, уникальные для установки A ( -ReferenceObject аргумент или первый позиционный аргумент), в то время как
  • '=>' указывает элементы, уникальные для набора B ( -DifferenceObject аргумент или второй позиционный аргумент).

Поэтому вам необходимо отфильтровать выходные объекты по их .SideIndicator значениям.
-PassThru Переключатель дополнительно гарантирует, что входные объекты будут переданы (в отличие от их переноса в [pscustomobject] экземпляр, который .InputObject их содержит).:

 $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 .

Примечание: Выше для краткости в качестве входных объектов используются строки; в вашем случае, поскольку вы работаете с объектами, возвращаемыми Get-Mailbox командлетом, и хотите сравнить их на основе .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 №4316, в котором предлагается расширение Compare-Object с помощью операций набора.

Комментарии:

1. Рад это слышать, @Brandon. В моем примере для краткости использовались строки. Я обновил ответ, чтобы включить ваше решение, включая альтернативу, в которой вы получаете все объекты почтового ящика в результатах, используя -Property Identity вместо этого.

Ответ №2:

Таким образом, это, по сути, практический пример теории множеств, т. Е. Я бы хотел, чтобы все элементы из набора 1, которых нет в наборе 2. PowerShell не имеет прямых командлетов для этого, но с помощью .В сети вы можете использовать библиотеки Microsoft Linq, чтобы выполнить эту работу за вас.

Единственная хитрость заключается в том, что вам нужно преобразовать переменные PowerShell в массивы объектов, чтобы вызов функции работал правильно:

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

Наконец, элементы, которые вы сравниваете в двух массивах, должны быть сопоставимы. Для простых вещей, таких как строки, это всегда работает. Если вещи, которые вы сравниваете, являются более сложными объектами, они могут быть несопоставимы напрямую.