Какого черта происходит с этим фильтром AD в PowerShell?

9

Я недавно написал этот ответ и наткнулся на что-то интересное.

get-aduser -filter {-not (description -eq "auto")} | measure-object

а также

get-aduser -filter {description -ne "auto"} | measure-object

возвращает две совершенно разные вещи при запуске с одними и теми же данными, при этом первая команда возвращает ожидаемое значение. На первый взгляд кажется, что пользователи с нулевым значением в поле описания не возвращаются в качестве совпадений во второй команде, даже если NULL явно не равно «auto».

Несколько человек в чате посмотрели на это и убедились, что я не сумасшедший. Что тут происходит?

MDMarra
источник
1
Интересно, что прокачка через Where-object и применение фильтра, который не работает выше, работает. get-aduser -filter * -Описание свойств | ? {$ _. description -ne "Авто"} | мера
Майк
Да @ Mike, это , кажется, поведение -neоператора сравнения в с -Filterединственным блоком. В частности, когда входное значение сравнения составляет $null.
Jscott
1
Нравится и не нравится, кажется, работают одинаково. {описание - не похоже на «что-то»} не работает, но {- нет (описание - как «что-то»)} работает. Кроме того, тот, который работает, требует значительно больше времени для оценки. Как сломанный не оценивает все объекты, которые он должен.
Майк
@ Майк Это верно. Я на самом деле наткнулся на это с помощью -notlikeпервоначально, но переключился на -neпосле того, как я понял, что я не получаю то, что я хотел. TBH, я забыл, что даже пробовал это делать, пока ты не упомянул об этом - но я также могу воспроизвести это.
MDMarra
2
Просто мысль, но, возможно, предложение PoSH -eq/ -neпытается вести себя как SQL =/ <>? В SQL, foo = NULLи foo <> NULLвсегда будет возвращать ложь, потому что NULL является «несравненный» - только foo IS NULLи foo IS NOT NULLспециальные операторы будут работать. Поведение должно быть аналогичным в PoSH, где ваш -not (foo -eq "bar")фильтр будет возвращать все, что (foo -eq "bar")вернуло $false, что foo -eq $nullбудет делать. Вместо этого, как насчет if (!foo -or foo -ne "bar")(эквивалентный SQL foo IS NULL OR foo <> 'bar')?
jimbobmcgee

Ответы:

4

Основное различие между ними заключается в том, что первая команда не предполагает прямого сравнения значений, чтобы получить все результаты, а вторая команда это делает. Первая команда содержит результаты NULL, а вторая - нет (как MDMarra уже обнаружила). Обе команды начинаются с этого командлета:

get-aduser

При просмотре ниже помните, что в результаты этого командлета включены все пользователи AD, независимо от того, что указано в -filterпараметре после него.

Теперь давайте разберем две разные части. Первый:

{-not (description -eq "auto")}

...средства

  1. "выяснить, где атрибут description равен текстовой строке" auto ". Чтобы это сравнение работало, в поле описания должна существовать строка, чтобы -eqоператор мог сравнить ее с" auto ". Значения NULL удаляются из этого сравнение, так как он не может сравнивать NULL со строковым значением.
  2. независимо от -eqПараметр фильтра дает мне ВСЕ, что НЕ является результатом (description -eq "auto"), который будет содержать значения NULL, поскольку исходный командлет get-aduserвключает в себя всех пользователей AD. Не нужно было сравнивать что-либо еще с -notоператором. Он просто дал вам все, кроме результатов (description -eq "auto")фильтра.

В вашем примере предположим, что у вас есть 1 пользователь AD, чье описание равно «auto», несколько сотен с чем-то отличным от «auto» и несколько сотен с NULL-описаниями. Пошаговая логика команд:

  1. Дайте мне всех пользователей AD (get-aduser), где описание равно "auto" - в результате 1 пользователь
  2. Дайте мне всех пользователей AD, которые НЕ являются тем, что вы только что дали мне - результат - несколько сотен с чем-то другим И несколько сотен, которые имеют NULL.

Поскольку с помощью -notоператора не нужно было сравнивать что-либо с чем-либо еще , в результате было получено описание пользователей NULL, которое было зафиксировано в исходном get-aduserкомандлете.

Вторая команда:

{description -ne "auto"}

...средства

  1. "выяснить, где атрибут description не равен точной строке" auto ". Опять же, чтобы это сравнение работало, в поле описания должна существовать строка, чтобы -neоператор мог сравнить ее с" auto ". Значения NULL удаляются из этого сравнения, поскольку он не может сравнить NULL со строковым значением.

В вашем примере снова предположим, что у вас есть 1 пользователь AD, чье описание равно «auto», несколько сотен с чем-то отличным от «auto» и несколько сотен с NULL-описаниями. Пошаговая логика команд:

  1. Дайте мне всех пользователей AD, где описание не равно "auto" - в результате получится несколько сотен пользователей с чем-то отличным от "auto" в их описании. Он не тянет пользователей с описаниями NULL, потому что он не может сравнивать NULL с текстовой строкой.

В любом случае вся разница между двумя командами определенно не интуитивна.

Используя эту команду, вы также сможете перехватывать значения NULL с "-and", например так:

{description -ne "auto" -and description -ne $NULL}

Я не на 100% по синтаксису, так как не могу проверить его прямо сейчас, и, вероятно, есть лучший способ сделать это, чем это тоже. Когда все это разбито, это довольно анти-климатическое и потребовало много печатания, чтобы объяснить, но я столкнулся с такими странными вещами, как это, прежде чем использовать различные операторы и много проб и ошибок, так как я никогда не могу вспомнить все предостережения которые согласуются с использованием каждого.

Ссылка: http://technet.microsoft.com/en-us/library/hh847732.aspx :

Операторы сравнения

Используйте операторы сравнения (-eq, -ne, -gt, -lt, -le, -ge) для сравнения значений и условий тестирования. Например, вы можете сравнить два строковых значения, чтобы определить, равны ли они.

Операторы сравнения включают в себя операторы сопоставления (-match, -notmatch), которые находят шаблоны с помощью регулярных выражений; оператор замены (-replace), который использует регулярные выражения для изменения входных значений; операторы like (-like, -notlike), которые находят шаблоны с использованием подстановочных знаков (*); и операторы содержания (in, -notin, -contains, -notcontains), которые определяют, появится ли тестовое значение в наборе ссылок.

Они также включают побитовые операторы (-bAND, -bOR, -bXOR, -bNOT) для управления битовыми комбинациями в значениях.

Для получения дополнительной информации см. About_Comparison_Operators

Логические Операторы

Используйте логические операторы (-and, -or, -xor, -not,!), Чтобы соединить условные операторы в один сложный условный оператор . Например, вы можете использовать логический оператор -and для создания фильтра объекта с двумя различными условиями.

Для получения дополнительной информации см. About_Logical_Operators.

августейший
источник
Хороший обзор, но почему нулевые значения исключаются из операторов -ne и -notlike? Это настоящий скребок головы. Мне интересно, есть ли в его дизайне какое-то эзотерическое объяснение спецификации .net или это ошибка или неожиданное поведение?
MDMarra
Подожди, просто читай внимательнее. Похоже, они сравнивают только строки, а нулевые атрибуты на самом деле являются нулевыми, а не пустой строкой. Интересно, если не интуитивно.
MDMarra
0

Добавим к этому старому вопросу, который возникает при поиске:

Использование -Filter с отрицательным соответствием, таким как -ne или -notlike, исключает результаты с пустыми нулевыми значениями. Чтобы они были включены, вам также необходимо явно сопоставить, используя -notlike '*', поскольку -eq '' и -eq $ NULL не являются допустимыми фильтрами. Обратите внимание, что это причуда с -Filter, использование прямого -LdapFilter ДЕЛАЕТ отрицательное совпадение с пустыми значениями.

Вот пример фильтра и LdapFilter для множественного совпадения с отрицательным:

Get-ADUser -Filter { mail -like '*example*' -and (description -ne 'example' -or description -notlike '*') }

Get-ADUser -LdapFilter '(&(mail=*example*)(!description=example))'
WhoIsRich
источник