Che diamine sta succedendo con questo filtro AD in PowerShell?


9

Di recente ho scritto questa risposta e mi sono imbattuto in qualcosa di interessante.

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

e

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

restituisce due cose molto diverse quando viene eseguito sugli stessi dati, con il primo comando che restituisce il valore previsto. A prima vista sembra che gli utenti con un valore nullo nel campo della descrizione non vengano restituiti come corrispondenze nel secondo comando, anche se NULL chiaramente non equivale a "auto".

Un paio di persone in chat hanno visto questo e verificato che non sono pazzo. Cosa sta succedendo qui?


1
Interessante che il piping attraverso Where-object e l'applicazione del filtro che non funziona sopra funzioni. get-aduser -filter * -Proprietà descrizione | ? {$ _. description -ne "Auto"} | misura
Mike

@Mike Sì, questo sembra essere il comportamento -nedell'operatore di confronto solo all'interno del -Filterblocco. In particolare, quando il valore di input del confronto è $null.
jscott,

1
Like e notlike sembrano funzionare in modo simile. {description -notlike "qualcosa"} non funziona, ma {-not (description -like "qualcosa")} funziona. Anche quello che funziona richiede molto più tempo per essere valutato. Come quello rotto non sta valutando tutti gli oggetti che dovrebbe.
Mike

@ Mike Esatto. In realtà mi sono imbattuto in questo usando -notlikeoriginariamente, ma sono passato a -nedopo aver realizzato che non stavo ottenendo quello che volevo. TBH, ho dimenticato di averlo provato fino a quando non lo hai menzionato, ma posso anche riprodurlo.
MDMarra,

2
Solo un pensiero ma forse la clausola -eq/ PoSH -necerca di comportarsi come un SQL =/ <>? In SQL, foo = NULLe foo <> NULLrestituisce sempre falso, perché NULL è 'incomparabile' - solo le foo IS NULLe foo IS NOT NULLspeciali operatori lavoreranno. Il comportamento deve essere simile in PoSH, in cui il -not (foo -eq "bar")filtro restituirà tutto ciò per cui è stato (foo -eq "bar")restituito $false, il che foo -eq $nullfarebbe. Invece, che ne dici di if (!foo -or foo -ne "bar")(equivalente SQL foo IS NULL OR foo <> 'bar')?
jimbobmcgee,

Risposte:


4

La differenza chiave tra i due è che il primo comando non comporta un confronto diretto dei valori per ottenere tutti i risultati, e il secondo comando lo fa. Il primo comando include i risultati NULL e il secondo no (come MDMarra ha già scoperto). Entrambi i comandi iniziano con questo cmdlet:

get-aduser

Quando si analizza il seguito, tenere presente che i risultati di questo cmdlet includono tutti gli utenti AD indipendentemente da qualsiasi altra cosa nel -filterparametro successivo.

Ora suddividiamo le due parti che sono diverse. Il primo:

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

...si intende

  1. "capire dove l'attributo description è uguale alla stringa di testo" auto ". Per far funzionare questo confronto, nel campo della descrizione deve esistere una stringa affinché l' -eqoperatore sia in grado di confrontarlo con" auto ". I valori NULL vengono eliminati da questo confronto poiché non può confrontare un valore NULL con un valore stringa.
  2. indipendentemente dal -eqIl parametro filter mi dà TUTTO ciò che NON è il risultato di (description -eq "auto"), che includerà NULL, perché il cmdlet originale get-aduser, include tutti gli utenti AD. Non è stato necessario confrontare nulla con qualcos'altro con l' -notoperatore. Ti ha dato tutto tranne i risultati del (description -eq "auto")filtro.

Nel tuo esempio supponi di avere 1 utente AD con una descrizione uguale a "auto", alcune centinaia con qualcosa di diverso da "auto" e alcune centinaia con descrizioni NULL. Passando attraverso la logica di comando farà:

  1. Dammi tutti gli utenti AD (get-aduser) in cui la descrizione equivale a "auto" - risulta in 1 utente
  2. Dammi tutti gli utenti AD che NON sono quello che mi hai appena dato - il risultato sono le poche centinaia con qualcos'altro E le poche centinaia che hanno NULL.

Poiché non è stato necessario confrontare nulla con qualsiasi altra cosa utilizzando l' -notoperatore, il risultato includeva gli utenti con descrizione NULL acquisiti nel get-adusercmdlet originale .

Il secondo comando:

{description -ne "auto"}

...si intende

  1. "capire dove l'attributo description non equivale alla stringa esatta" auto ". Anche in questo caso, affinché questo confronto funzioni, nel campo della descrizione deve esistere una stringa affinché l' -neoperatore possa confrontarla con" auto ". Valori NULL vengono eliminati da questo confronto poiché non può confrontare un valore NULL con un valore di stringa.

Nel tuo esempio supponiamo di avere 1 utente AD con una descrizione uguale a "auto", alcune centinaia con qualcosa di diverso da "auto" e alcune centinaia con descrizioni NULL. Passando attraverso la logica di comando farà:

  1. Dammi tutti gli utenti AD in cui la descrizione non è uguale a "auto" - risulta nelle poche centinaia di utenti con qualcosa di diverso da "auto" nella loro descrizione. Non attira gli utenti con le descrizioni NULL perché non può confrontare un NULL con una stringa di testo.

In ogni caso, l'intera differenza tra i due comandi è decisamente non intuitiva.

Usando questo comando dovresti essere in grado di catturare i NULL con un "-e" dentro così:

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

Non sono al 100% sulla sintassi poiché non riesco a provarla in questo momento, e probabilmente c'è un modo migliore per farlo anche di questo. Quando è tutto analizzato, è abbastanza anti-climatico e ci sono voluti un sacco di battute per spiegare, ma ho incontrato cose strane come questa prima di usare i vari operatori e molte prove ed errori dato che non ricordo mai tutte le avvertenze che vanno di pari passo con l'uso di ognuno.

Riferimento: http://technet.microsoft.com/en-us/library/hh847732.aspx :

Operatori di confronto

Utilizzare gli operatori di confronto (-eq, -ne, -gt, -lt, -le, -ge) per confrontare i valori e le condizioni di prova. Ad esempio, è possibile confrontare due valori di stringa per determinare se sono uguali.

Gli operatori di confronto includono gli operatori di corrispondenza (-match, -notmatch), che trovano schemi usando espressioni regolari; l'operatore di sostituzione (-replace), che utilizza espressioni regolari per modificare i valori di input; gli operatori simili (-like, -notlike), che trovano schemi usando caratteri jolly (*); e gli operatori di contenimento (in, -notin, -contains, -notcontains), che determinano se un valore di test appare in un set di riferimento.

Includono anche gli operatori bit a bit (-bAND, -bOR, -bXOR, -bNOT) per manipolare i pattern di bit nei valori.

Per ulteriori informazioni, vedere about_Comparison_Operators

Operatori logici

Utilizzare operatori logici (-and, -or, -xor, -not,!) Per collegare le istruzioni condizionali in un singolo condizionale complesso . Ad esempio, è possibile utilizzare un operatore logico e per creare un filtro oggetti con due diverse condizioni.

Per ulteriori informazioni, consultare about_Logical_Operators.


Buona panoramica sicuramente, ma perché i valori null sono esclusi dagli operatori -ne e -nlike? Questo è il vero grattacapo. Mi chiedo se la sua progettazione abbia qualche spiegazione esoterica delle specifiche .net o se si tratta di un bug o di un comportamento imprevisto?
MDMarra,

Aspetta, leggi più da vicino. Sembra che confrontino solo stringhe e gli attributi null siano in realtà null e non una stringa vuota. Interessante se non intuitivo.
MDMarra,

0

Aggiungendo a questa vecchia domanda come si presenta durante la ricerca:

L'uso di -Filter con corrispondenza negativa come -ne o -notlike esclude i risultati con valori nulli vuoti. Per essere inclusi, devi anche abbinare esplicitamente usando -notlike '*' as -eq '' e -eq $ NULL non sono filtri validi. Si noti che questa è una stranezza con -Filter, usando un -LdapFilter diretto FA valori negativi corrispondenti a vuoti.

Ecco un esempio di Filter e LdapFilter di multi match con negativo:

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

Get-ADUser -LdapFilter '(&(mail=*example*)(!description=example))'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.