O que diabos está acontecendo com esse filtro do AD no PowerShell?

9

Eu escrevi recentemente essa resposta e me deparei com algo interessante.

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

e

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

retorne duas coisas muito diferentes quando executadas nos mesmos dados, com o primeiro comando retornando o valor esperado. Parece à primeira vista que usuários com um valor nulo no campo de descrição não são retornados como correspondências no segundo comando, mesmo que NULL claramente não seja igual a "automático".

Algumas pessoas no chat analisaram isso e verificaram que não sou louco. O que está acontecendo aqui?

MDMarra
fonte
1
Interessante que o canal através do objeto Where e a aplicação do filtro que não funciona acima funcionam. get-aduser -filter * -Properties descrição | ? {$ _. description -ne "Auto"} | medida
Mike
@ Mike Sim, este parece ser o comportamento do -neoperador de comparação apenas dentro do -Filterbloco. Especificamente, quando o valor de entrada da comparação é $null.
Jscott
1
Gosto e não parecem funcionar da mesma forma. {description-notlike "something"} não funciona, mas {-not (descrição-likelike "something")} funciona. Também o que funciona leva consideravelmente mais tempo para avaliar. Como o quebrado não está avaliando todos os objetos que deveria.
Mike
@ Mike Isso mesmo. Na verdade, eu tropecei nisso usando -notlikeoriginalmente, mas mudei para -nedepois que percebi que não estava conseguindo o que queria. TBH, esqueci que tinha tentado isso até você mencionar - mas também posso reproduzi-lo.
precisa saber é o seguinte
2
Apenas um pensamento, mas talvez a cláusula -eq/ PoSH -netente se comportar como um SQL =/ <>? No SQL, foo = NULLe foo <> NULLsempre retornará false, porque NULL é 'incomparável' - apenas os operadores especial foo IS NULLe foo IS NOT NULLirão funcionar. O comportamento deve ser semelhante no PoSH, onde seu -not (foo -eq "bar")filtro retornaria tudo o que (foo -eq "bar")retornasse $false, o que foo -eq $nullseria. Em vez disso, que tal if (!foo -or foo -ne "bar")(SQL equivalente foo IS NULL OR foo <> 'bar')?
precisa saber é o seguinte

Respostas:

4

A principal diferença entre os dois é que o primeiro comando não envolve uma comparação direta de valores para obter todos os resultados, e o segundo comando. O primeiro comando inclui resultados NULL e o segundo não (como o MDMarra já descobriu). Ambos os comandos começam com este cmdlet:

get-aduser

Ao analisar o abaixo, lembre-se de que os resultados desse cmdlet incluem todos os usuários do AD, independentemente de qualquer outra coisa no -filterparâmetro após ele.

Agora vamos dividir as duas partes que são diferentes. O primeiro:

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

...significa

  1. "descubra onde o atributo description é igual à string de texto" auto ". Para que essa comparação funcione, é necessário que exista uma string no campo de descrição para que o -eqoperador possa compará-la com" auto ". Valores nulos são eliminados comparação, pois não pode comparar um NULL a um valor de sequência.
  2. independentemente do -eqO parâmetro filter fornece-me TUDO que NÃO é o resultado de (description -eq "auto"), que incluirá NULLs, porque o cmdlet original get-aduserinclui todos os usuários do AD. Não era necessário comparar nada com o -notoperador. Apenas lhe deu tudo, além dos resultados do (description -eq "auto")filtro.

No seu exemplo, suponha que você tenha 1 usuário do AD com a descrição igual a "auto", algumas centenas com algo diferente de "auto" e algumas centenas com descrições NULL. Percorrendo a lógica de comando, ele fará:

  1. Dê-me todos os usuários do AD (get-aduser) em que a descrição seja igual a "auto" - resulta em 1 usuário
  2. Dê-me todos os usuários do AD que NÃO são o que você acabou de me dar - o resultado são as poucas centenas com outra coisa E as poucas centenas que têm NULL.

Como não era necessário comparar nada com o -notoperador, o resultado incluiu a descrição NULL de usuários capturados no get-adusercmdlet original .

O segundo comando:

{description -ne "auto"}

...significa

  1. "descubra onde o atributo description não é igual à string exata" auto ". Novamente, para que essa comparação funcione, uma string precisa existir no campo de descrição para que o -neoperador possa compará-la com" auto ". Valores NULL são descartados dessa comparação, pois não é possível comparar um NULL a um valor de sequência.

No seu exemplo, novamente, suponha que você tenha 1 usuário do AD com a descrição igual a "auto", algumas centenas com algo diferente de "auto" e algumas centenas com descrições NULL. Percorrendo a lógica de comando, ele fará:

  1. Dê-me todos os usuários do AD em que a descrição não seja igual a "automático" - resulta em poucas centenas de usuários com algo diferente de "automático" em sua descrição. Ele não puxa os usuários com descrições NULL porque não pode comparar um NULL a uma sequência de texto.

De qualquer maneira, toda a diferença entre os dois comandos é definitivamente não intuitiva.

Usando este comando, você poderá capturar os NULLs com um "-and" também, como este:

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

Não sou 100% da sintaxe, pois não posso testá-la agora, e provavelmente existe uma maneira melhor de fazer isso do que isso também. Quando tudo está quebrado, é bastante anti-climático e demorou bastante para ser explicado, mas já me deparei com coisas estranhas como essa antes de usar os vários operadores e muitas tentativas e erros, pois nunca consigo me lembrar de todas as advertências que combinam com o uso de cada um.

Referência: http://technet.microsoft.com/en-us/library/hh847732.aspx :

Operadores de comparação

Use operadores de comparação (-eq, -ne, -gt, -lt, -le, -ge) para comparar valores e condições de teste. Por exemplo, você pode comparar dois valores de sequência para determinar se são iguais.

Os operadores de comparação incluem os operadores de correspondência (-match, -notmatch), que encontram padrões usando expressões regulares; o operador replace (-replace), que usa expressões regulares para alterar os valores de entrada; os operadores like (-like, -notlike), que encontram padrões usando caracteres curinga (*); e os operadores de contenção (em, -notin, -contains, -notcontains), que determinam se um valor de teste aparece em um conjunto de referência.

Eles também incluem os operadores bit a bit (-bAND, -bOR, -bXOR, -bNOT) para manipular os padrões de bits nos valores.

Para mais informações, consulte about_Comparison_Operators

Operadores lógicos

Use operadores lógicos (-e, -ou, -xor, -not,!) Para conectar instruções condicionais em uma única condicional complexa . Por exemplo, você pode usar um operador lógico - e para criar um filtro de objeto com duas condições diferentes.

Para mais informações, consulte about_Logical_Operators.

agosto
fonte
Boa visão geral, com certeza, mas por que os valores nulos são excluídos dos operadores -ne e -notlike? Esse é o verdadeiro arranhador de cabeça. Eu estou querendo saber se é por design um tem alguma explicação esotérica .net spec ou se é um bug ou comportamento inesperado?
precisa saber é o seguinte
Espere, basta ler mais de perto. Parece que eles só comparam cadeias e os atributos nulos são realmente nulos e não uma cadeia vazia. Interessante se não intuitivo.
precisa saber é o seguinte
0

Adicionando a essa pergunta antiga conforme ela aparece ao pesquisar:

O uso de -Filter com correspondência negativa, como -ne ou -notlike, exclui resultados com valores nulos vazios. Para que eles sejam incluídos, você também precisa corresponder explicitamente usando -notlike '*' como -eq '' e -eq $ NULL não são filtros válidos. Observe que isso é uma peculiaridade com -Filter, usando um negativo -LdapFilter DOES corresponde a valores vazios.

Aqui está um exemplo de filtro e LdapFilter de correspondência múltipla com negativo:

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

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