Що, до біса, відбувається з цим фільтром AD в PowerShell?


9

Нещодавно я написав цю відповідь і натрапив на щось цікаве.

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

і

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

повертає дві дуже різні речі при запуску проти одних і тих же даних, при цьому перша команда повертає очікуване значення. На перший погляд здається, що користувачі з нульовим значенням у полі опису не повертаються як збіги у другій команді, навіть якщо NULL явно не дорівнює "авто".

Пару людей у ​​чаті переглянули це і переконалися, що я не божевільний. Що тут відбувається?


1
Цікаво, що прошивка його через Where-object та застосування фільтра, який не працює вище, працює. get-aduser -filter * -Опис властивостей | ? {$ _. опис -ne "Авто"} | міра
Майк

@Mike Так, схоже, це поведінка -neоператора порівняння лише в -Filterблоці. Зокрема, коли вхідне значення порівняння $null.
jscott

1
Як і не схоже, схоже, працює аналогічно. {description -notlike "щось"} не працює, але {-not (опис -like "щось")} працює. Також те, що працює, займає значно більше часу. Як і битий, він не оцінює всі об'єкти, які він повинен.
Майк

@Mike Правильно. Я фактично натрапив на це, використовуючи -notlikeспочатку, але перейшов до -neтого, як зрозумів, що не отримую того, що хотів. ТБХ, я забув, що навіть намагався це зробити, поки ти не згадав про це, - але я можу це також відтворити.
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. "з'ясуйте, де атрибут опису дорівнює текстовому рядку" auto ". Щоб це порівняння працювало, у полі опису повинен існувати рядок, щоб -eqоператор міг порівнювати його з" auto ". З цього значення випадають значення NULL порівняння, оскільки він не може порівняти NULL зі значенням рядка.
  2. незалежно від -eqПараметр фільтра дав мені ВСЕ, що НЕ є результатом (description -eq "auto"), який буде включати NULL, тому що оригінальний командлет get-aduserвключає всіх користувачів AD. Не потрібно було нічого порівнювати з -notоператором. Це просто дало вам усе, крім того, які були результати (description -eq "auto")фільтра.

У вашому прикладі, припустимо, у вас є користувач AD AD, який має їх опис, рівний "auto", кілька сотень із чимось іншим, ніж "auto" та кілька сотень з NULL описами. Перейшовши через логіку команди, вона виконає:

  1. Дайте мені всіх користувачів AD (get-aduser), де опис дорівнює "auto" - приводить до 1 користувача
  2. Дайте мені всіх користувачів AD, які НЕ є тим, що ви мені щойно подарували - результат - це кілька сотень із чимось іншим І кілька сотень, які мають НУЛЛ.

Оскільки йому не довелося нічого порівнювати з будь-яким іншим, використовуючи -notоператор, результат включав користувачів опису NULL, які були захоплені в оригінальному get-aduserкомандлеті.

Друга команда:

{description -ne "auto"}

...засоби

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

У вашому прикладі ще раз припустимо, що у вас є користувач 1 AD, який має їх опис, рівний "auto", кілька сотень із чимось іншим, ніж "auto" і кілька сотень з NULL описами. Перейшовши через логіку команди, вона виконає:

  1. Дайте мені всім користувачам AD, де опис не дорівнює "авто" - це призводить до декількох сотень користувачів із чимось відмінним від "авто" в їх описі. Він не тягне користувачів з описами NULL, оскільки він не може порівнювати NULL з текстовим рядком.

У будь-якому випадку вся різниця між двома командами, безумовно, не інтуїтивно зрозуміла.

Використовуючи цю команду, ви повинні мати змогу ловити NULL з "-і" там теж так:

{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), які знаходять шаблони, використовуючи регулярні вирази; оператор заміни (-замінити), який використовує регулярні вирази для зміни вхідних значень; подібні оператори (-like, -notlike), які знаходять шаблони, використовуючи символи підстановки (*); і оператори стримування (in, -notin, -contains, -notcontains), які визначають, чи є тестове значення в контрольному наборі.

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

Докладнішу інформацію див. У розділі about_Comppare_Operators

Логічні оператори

Використовуйте логічні оператори (-and, -or, -xor, -not,!) Для з'єднання умовних операторів у єдиний складний умовний . Наприклад, ви можете використовувати логічний оператор-оператор для створення об'єктного фільтра з двома різними умовами.

Для отримання додаткової інформації див. Про_Логічні_Оператори.


Гарний огляд напевно, але чому нульові значення виключені з операторів -ne і -notlike? Ось справжній дряпальник голови. Мені цікаво, чи в його дизайні є якесь езотеричне роз'яснення .net spec, чи це помилка чи несподівана поведінка?
MDMarra

Зачекайте, просто читайте уважніше. Схоже, вони порівнюють лише рядки, а атрибути null насправді є null, а не порожніми рядками. Цікаво, якщо неінтуїтивно.
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))'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.