PowerShell -Like vs -Contém Operadores de Comparação

Em algum momento durante a sua carreira PowerShell terá de testar se “algo” é encontrado (ou não encontrado) dentro de um determinado objecto. Descobri que normalmente sou confrontado com esta situação quando estou a testar se uma string “contém” um valor ou não.

Neste momento, fico sempre confuso quanto ao operador de comparação a utilizar. De uma perspectiva de linguagem lógica, sinto sempre que -contains é o caminho a seguir, mas depois lembro-me que essa pode não ser a escolha correcta.

Para colocar esta questão de uma vez por todas (pelo menos para mim), aqui está um resumo de quando usar -like e quando usar -contains.

PowerShell -like Comparison Operator

Aqui está como o Microsoft TechNet descreve a utilização para -like:

-Like
Description:
Match using the wildcard character (*).

Exemplo:
PS C:\> “Windows PowerShell” -like “*shell”
True

PS C:\> “Windows PowerShell”, “Servidor” -como “*shell”
Windows PowerShell

Aqui está a minha versão:

-like é usado para comparar ou descobrir se uma corda existe dentro de outra corda. -like permite-lhe utilizar o wildcard (*) para que possa procurar em qualquer lugar dentro da cadeia de caracteres.

Então voltando ao meu requisito inicial de determinar se uma string contém ou não um determinado valor, utilizaríamos o operador -like. Ver alguns exemplos abaixo:

$SearchTerm = 'xyz'$String = 'abc def ghi jkl mno pqr stu vw xyz'If ($String -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }# Result = False

No exemplo 1, o resultado é falso porque não existem wildcards, portanto a sua verificação para ver se a string corresponde exactamente.

$SearchTerm = 'xyz*'$String = 'abc def ghi jkl mno pqr stu vw xyz'If ($String -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }# Result = False

No exemplo 2 adicionámos o wildcard (*) no final do termo de pesquisa. Isto significa essencialmente verificar se xyz existe no início da cadeia de caracteres e depois ignorar o resto. Neste caso não existe, daí o resultado ser falso.

$SearchTerm = 'abc*'$String = 'abc def ghi jkl mno pqr stu vw xyz'If ($String -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }# Result = True

No exemplo 3 estamos a fazer o mesmo que no exemplo 2, mas procurando por abc* e por isso retorna verdadeiro porque abc é encontrado no início da cadeia de caracteres. O resto é então ignorado devido ao wildcard.

$SearchTerm = '*xyz'$String = 'abc def ghi jkl mno pqr stu vw xyz'If ($String -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }# Result = True

Exemplo 4 é essencialmente um inverso do exemplo 3. Estamos a procurar por xyz no fim da cadeia de caracteres e não nos importamos com nada na frente dela (daí o wildcard na frente do termo de pesquisa).

$SearchTerm = '*mno*'$String = 'abc def ghi jkl mno pqr stu vw xyz'If ($String -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }# Result = True

Exemplo 5 mostra a procura de algo no meio da cadeia de caracteres utilizando wildcards em ambos os lados do termo de pesquisa.

PowerShell -contém Operador de Comparação

Aqui está como o Microsoft TechNet descreve a utilização para -contains:

Descrição:
Operador de contenção. Diz se uma colecção de valores de referência inclui um único valor de teste. Retorna sempre um valor booleano. Retorna VERDADEIRO apenas quando o valor do teste corresponde exactamente a pelo menos um dos valores de referência.

Quando o valor do teste é uma colecção, o operador Contém utiliza a igualdade de referência. Retorna VERDADEIRO apenas quando um dos valores de referência é a mesma instância do objecto de valor de teste.

Sintax:
-Contém

p>Exemplos:
PS C:\\\i>> “abc”, “def” – Contém “def”
Verdade

PS C:\> “Windows”, “PowerShell” -Contém “Shell”
Falso #Não coincide exactamente

# A lista de computadores em $domainServers
# inclui $esteComputador?
# ————–
PS C:\> $domainServers – Contém $thisComputer
True

PS C:\> “abc”, “def”, “ghi” – Contém “abc”, “def”
False

PS C:\> $a = “abc”, “def”
PS C:\> “abc”, “def”, “ghi” -Contém $a
False
PS C:\> $a, “ghi” – Contém $a
True

Agora aqui está a minha versão….

O -contains operador de comparação é utilizado para determinar se uma colecção de objectos (por exemplo, uma matriz) contém ou não um determinado objecto. A avaliação é completada em relação a todo o objecto e não a qualquer propriedade de objecto individual. Por outras palavras, todas as propriedades do objecto são levadas em consideração.

Isso pode ser um pouco confuso, mas olhando para alguns exemplos pode esclarecer um pouco as coisas:

$SearchTerm = 'xyz'$Collection = 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vw', 'xyz'If ($Collection -contains $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }#Result = True

O primeiro exemplo é fácil, um array com cada objecto como uma string e, portanto, torna a comparação realmente fácil. O exemplo acima é a procura do objecto de matriz (elemento de matriz) de xyz. Como existe um elemento de matriz que corresponde a xyz, ele retornará verdadeiro.

$SearchTerm = 'W32Time'$Collection = Get-ServiceIf ($Collection -contains $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }#Result = False

Agora seria de esperar que o exemplo acima retornasse verdadeiro, porque cada sistema Windows tem um serviço W32Time, mas não… porquê? Bem, porque estamos a tentar encontrar um objecto baseado numa única propriedade, name. O operador -contains não funciona assim, no entanto. Compara todas as propriedades do objecto e se todas elas forem iguais, então retorna Verdadeiro, senão retorna Falso.

No exemplo acima, estamos essencialmente a comparar um objecto de corda com um objecto System.ServiceProcess.ServiceController, que não vai funcionar.

Para encontrar um serviço com o name propriedade que precisaríamos de fazer:

$SearchTerm = 'W32Time'$Collection = Get-ServiceIf ($Collection -like $SearchTerm) { Write-Output 'True' } Else { Write-Output 'False' }#Result = True

Embora isto funcione, pode não ser o melhor resultado porque W32Time pode ser o valor de uma propriedade dentro de outro serviço e, portanto, pode obter alguns falsos positivos.

Para remover o risco de falsos positivos, eu faria pessoalmente algo como:

$SearchTerm = 'W32Time'$Collection = Get-ServiceForEach ($Service in $Collection) { If ($Service.Name -eq $SearchTerm) { Write-Output 'True' }}#Result = True

Enumerar todos os serviços da colecção e determinar se cada um dos seus name propriedades iguais ao termo de pesquisa é uma forma muito precisa de determinar se o serviço em particular existe ou não e eliminará todos os falsos positivos. Mais código, mas uma solução melhor.

Não Pesquisas?

Como uma nota lateral rápida, o que acontece se quiser determinar se algo não contém um determinado termo de pesquisa?

Bem nesse caso use apenas -NotLike ou -NotContains da mesma forma e nas mesmas situações em que usaria -like e -contains.

Mais informações sobre os Operadores de Comparação

Se quiser saber mais sobre todos os operadores de comparação, então consulte a página dos Operadores de Comparação TechNet.

Bem espero que isso ajude a tornar as coisas um pouco mais claras sobre quando usar -Like e quando usar -Contains.

Deixe-me saber os seus pensamentos abaixo…

Espanholas
Luca

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *