Qu'est-ce qui se passe avec ce filtre AD dans PowerShell?

9

J'ai récemment écrit cette réponse et suis tombé sur quelque chose d'intéressant.

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

et

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

retourner deux choses très différentes lorsqu'il est exécuté sur les mêmes données, la première commande renvoyant la valeur attendue. Il apparaît à première vue que les utilisateurs avec une valeur nulle dans le champ de description ne sont pas retournés en tant que correspondances dans la deuxième commande, même si NULL n'est clairement pas égal à "auto".

Quelques personnes dans le chat ont regardé cela et ont vérifié que je ne suis pas fou. Que se passe t-il ici?

MDMarra
la source
1
Il est intéressant de noter que le passage à travers Where-object et l'application du filtre qui ne fonctionne pas ci-dessus fonctionne. get-aduser -filter * -Description des propriétés | ? {$ _. description -ne "Auto"} | mesure
Mike
@Mike Oui, cela semble être le comportement de l' -neopérateur de comparaison uniquement dans le -Filterbloc. Plus précisément, lorsque la valeur d'entrée de la comparaison est $null.
jscott
1
Le semblable et le différent ne semblent pas fonctionner de la même façon. {description -notlike "something"} ne fonctionne pas, contrairement à {-not (description -like "something")}. De plus, celui qui fonctionne prend beaucoup plus de temps à évaluer. Comme le cassé n'évalue pas tous les objets qu'il devrait.
Mike
@ Mike C'est vrai. En fait, je suis tombé sur cette utilisation à l' -notlikeorigine, mais -neje suis passé à après avoir réalisé que je n'obtenais pas ce que je voulais. TBH, j'ai oublié que j'avais même essayé jusqu'à ce que vous en parliez - mais je peux aussi le reproduire.
MDMarra
2
Juste une pensée mais peut-être que la clause -eq/ de PoSH -neessaie de se comporter comme un SQL =/ <>? En SQL, foo = NULLet foo <> NULLretournera toujours false, car NULL est «incomparable» - seuls les opérateurs spéciaux foo IS NULLet foo IS NOT NULLfonctionneront. Le comportement doit être similaire dans PoSH, où votre -not (foo -eq "bar")filtre retournerait tout ce qui (foo -eq "bar")est retourné $false, ce qui foo -eq $nullferait l'affaire. Au lieu de cela, qu'en est-il if (!foo -or foo -ne "bar")(équivalent SQL foo IS NULL OR foo <> 'bar')?
jimbobmcgee

Réponses:

4

La principale différence entre les deux est que la première commande n'implique pas une comparaison directe des valeurs pour obtenir tous les résultats, et la deuxième commande le fait. La première commande inclut les résultats NULL et la seconde non (comme MDMarra l'a déjà découvert). Les deux commandes commencent par cette applet de commande:

get-aduser

Lorsque vous parcourez les étapes ci-dessous, n'oubliez pas que les résultats de cette applet de commande incluent tous les utilisateurs AD indépendamment de toute autre chose dans le -filterparamètre suivant.

Maintenant, décomposons les deux parties qui sont différentes. Le premier:

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

...veux ​​dire

  1. "déterminer où l'attribut de description est égal à la chaîne de texte" auto ". Pour que cette comparaison fonctionne, une chaîne doit exister dans le champ de description pour que l' -eqopérateur puisse la comparer à" auto ". Les valeurs NULL sont supprimées de cette comparaison car il ne peut pas comparer un NULL à une valeur de chaîne.
  2. indépendamment du -eqle paramètre de filtre me donne TOUT ce qui N'EST PAS le résultat de (description -eq "auto"), qui inclura des NULLs, car l'applet de commande d'origine,, get-aduserinclut tous les utilisateurs AD. Il n'a pas eu à comparer quoi que ce soit à l' -notopérateur avec l' opérateur. Il vous a juste donné tout en plus des résultats du (description -eq "auto")filtre.

Dans votre exemple, supposons que vous ayez 1 utilisateur AD dont la description est égale à "auto", quelques centaines avec autre chose que "auto" et quelques centaines avec des descriptions NULL. En parcourant la logique de commande, il fera:

  1. Donnez-moi tous les utilisateurs AD (get-aduser) où la description est égale à "auto" - résulte en 1 utilisateur
  2. Donnez-moi tous les utilisateurs AD qui ne sont PAS ce que vous venez de me donner - le résultat est les quelques centaines avec quelque chose d'autre ET les quelques centaines qui ont NULL.

Comme il n'a pas eu à comparer quoi que ce soit à quoi que ce soit d'autre à l'aide de l' -notopérateur, le résultat inclut les utilisateurs de description NULL qui ont été capturés dans l' get-aduserapplet de commande d' origine .

La deuxième commande:

{description -ne "auto"}

...veux ​​dire

  1. "déterminer où l'attribut de description n'est pas égal à la chaîne exacte" auto ". Encore une fois, pour que cette comparaison fonctionne, une chaîne doit exister dans le champ de description pour que l' -neopérateur puisse la comparer à" auto ". Valeurs NULL sont supprimés de cette comparaison car il ne peut pas comparer un NULL à une valeur de chaîne.

Dans votre exemple, supposons à nouveau que vous avez 1 utilisateur AD dont la description est égale à "auto", quelques centaines avec autre chose que "auto" et quelques centaines avec des descriptions NULL. En parcourant la logique de commande, il fera:

  1. Donnez-moi tous les utilisateurs AD dont la description n'est pas égale à "auto" - résulte en quelques centaines d'utilisateurs avec quelque chose d'autre que "auto" dans leur description. Il ne tire pas les utilisateurs avec des descriptions NULL car il ne peut pas comparer un NULL à une chaîne de texte.

Quoi qu'il en soit, toute la différence entre les deux commandes n'est certainement pas intuitive.

En utilisant cette commande, vous devriez également pouvoir attraper les NULLs avec un "-and" comme ceci:

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

Je ne suis pas à 100% sur la syntaxe car je ne peux pas le tester pour le moment, et il y a probablement une meilleure façon de le faire que cela aussi. Quand tout est en panne, c'est assez anti-climatique et il a fallu beaucoup de frappe pour l'expliquer, mais j'ai rencontré des trucs bizarres comme celui-ci avant d'utiliser les différents opérateurs et beaucoup d'essais et d'erreurs car je ne me souviens jamais de toutes les mises en garde qui vont de pair avec l'utilisation de chacun.

Référence: http://technet.microsoft.com/en-us/library/hh847732.aspx :

Opérateurs de comparaison

Utilisez les opérateurs de comparaison (-eq, -ne, -gt, -lt, -le, -ge) pour comparer les valeurs et les conditions de test. Par exemple, vous pouvez comparer deux valeurs de chaîne pour déterminer si elles sont égales.

Les opérateurs de comparaison incluent les opérateurs de correspondance (-match, -notmatch), qui trouvent des modèles à l'aide d'expressions régulières; l'opérateur replace (-replace), qui utilise des expressions régulières pour modifier les valeurs d'entrée; les opérateurs similaires (-like, -notlike), qui trouvent des modèles à l'aide de caractères génériques (*); et les opérateurs de confinement (in, -notin, -contains, -notcontains), qui déterminent si une valeur de test apparaît dans un ensemble de référence.

Ils incluent également les opérateurs au niveau du bit (-bAND, -bOR, -bXOR, -bNOT) pour manipuler les modèles de bits dans les valeurs.

Pour plus d'informations, consultez about_Comparison_Operators

Opérateurs logiques

Utilisez des opérateurs logiques (-and, -or, -xor, -not,!) Pour connecter des instructions conditionnelles en une conditionnelle complexe unique . Par exemple, vous pouvez utiliser un opérateur logique et pour créer un filtre d'objet avec deux conditions différentes.

Pour plus d'informations, consultez about_Logical_Operators.

août
la source
Bon aperçu, bien sûr, mais pourquoi les valeurs nulles sont-elles exclues des opérateurs -ne et -notlike? C'est le vrai gratte-tête. Je me demande si sa conception a une explication ésotérique .net ou si c'est un bug ou un comportement inattendu?
MDMarra
Attendez, lisez plus attentivement. Il semble qu'ils ne comparent que les chaînes et que les attributs null sont en fait null et non une chaîne vide. Intéressant s'il n'est pas intuitif.
MDMarra
0

Ajout à cette vieille question telle qu'elle apparaît lors de la recherche:

L'utilisation de -Filter avec une correspondance négative telle que -ne ou -notlike exclut les résultats avec des valeurs nulles vides. Pour qu'ils soient inclus, vous devez également faire correspondre explicitement en utilisant -notlike '*' as -eq '' et -eq $ NULL ne sont pas des filtres valides. Notez qu'il s'agit d'une bizarrerie avec -Filter, en utilisant un direct -LdapFilter DOES négatif correspond aux valeurs vides.

Voici un exemple de correspondance multiple avec filtre et LdapFilter avec négatif:

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

Get-ADUser -LdapFilter '(&(mail=*example*)(!description=example))'
WhoIsRich
la source