PowerShell -Like vs -Contains Opérateurs de comparaison

À un moment donné de votre carrière de PowerShelling, vous devrez tester si « quelque chose » se trouve (ou non) dans un certain objet. Je constate que je suis généralement confronté à cette situation lorsque je teste si une chaîne de caractères « contient » une valeur ou non.

À ce stade, je suis toujours confus quant à l’opérateur de comparaison à utiliser. Du point de vue du langage logique, j’ai toujours l’impression que -contains est la voie à suivre, mais je me souviens ensuite que ce n’est peut-être pas le bon choix.

Pour mettre cette question au clair une fois pour toutes (du moins pour moi), voici un résumé de quand utiliser -like et quand utiliser -contains.

Opérateur de comparaison PowerShell -like

Voici comment Microsoft TechNet décrit l’utilisation de -like:

Like
Description:
Rattraper en utilisant le caractère générique (*).

Exemple:
PS C:\> « Windows PowerShell » -like « *shell »
True

PS C :\> « Windows PowerShell », « Server » -like « *shell »
Windows PowerShell

Voici ma version :

-like est utilisé pour comparer ou trouver si une chaîne de caractères existe dans une autre chaîne de caractères. -like permet d’utiliser le caractère générique (*) afin de pouvoir effectuer une recherche n’importe où dans la chaîne.

Pour en revenir à mon besoin initial de déterminer si une chaîne de caractères contient une valeur particulière ou non, nous utiliserions l’opérateur -like. Voir quelques exemples ci-dessous:

$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

Dans l’exemple 1, le résultat est faux car il n’y a pas de jokers, donc sa vérification pour voir si la chaîne correspond exactement.

$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

Dans l’exemple 2, nous avons ajouté le joker (*) à la fin du terme de recherche. Cela signifie essentiellement vérifier si xyz existe au début de la chaîne de caractères, puis ignorer le reste. Dans ce cas, ce n’est pas le cas, donc le résultat est faux.

$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

Dans l’exemple 3, nous faisons la même chose que dans l’exemple 2 mais nous recherchons abc* et renvoie donc vrai car abc est trouvé au début de la chaîne. Le reste est ensuite ignoré en raison du caractère générique.

$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

L’exemple 4 est essentiellement l’inverse de l’exemple 3. Nous recherchons xyz à la fin de la chaîne et ne nous soucions pas de tout ce qui se trouve devant (d’où le caractère générique au début du terme de recherche).

$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

L’exemple 5 montre la recherche de quelque chose au milieu de la chaîne en utilisant des caractères génériques de chaque côté du terme de recherche.

Opérateur de comparaison PowerShell -contains

Voici comment Microsoft TechNet décrit l’utilisation de -contains:

Description:
Opérateur de comparaison. Indique si une collection de valeurs de référence comprend une seule valeur de test. Renvoie toujours une valeur booléenne. Renvoie VRAI uniquement lorsque la valeur test correspond exactement à au moins une des valeurs de référence.

Lorsque la valeur test est une collection, l’opérateur Contient utilise l’égalité de référence. Il ne renvoie VRAI que si l’une des valeurs de référence est la même instance de l’objet valeur de test.

Syntaxe:
-Contenu

Exemples:
PS C:\div> « abc », « def » -Contenu « def »
True

PS C :\> « Windows », « PowerShell » -Contenu « Shell »
False #Not an exact match

# Does the list of computers in $domainServers
# include $thisComputer ?
# ————–
PS C:\> $domainServers -Contenu $thisComputer
True

PS C:\> « abc », « def », « ghi » -Contenu « abc », « def »
False

PS C :\> $a = « abc », « def »
PS C:\> « abc », « def », « ghi » -Contenu $a
False
PS C :\> $a, « ghi » -Contenu $a
True

Voici ma version…..

L’opérateur de comparaison -contains est utilisé pour déterminer si une collection d’objets (par exemple un tableau) contient ou non un objet particulier. L’évaluation est effectuée par rapport à l’objet entier et non par rapport à une seule propriété de l’objet. En d’autres termes, toutes les propriétés de l’objet sont prises en considération.

Cela pourrait être un peu déroutant, mais regarder quelques exemples pourrait éclaircir quelque peu les choses:

$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

Le premier exemple est facile, un tableau dont chaque objet est une chaîne de caractères et rend donc la comparaison vraiment facile. L’exemple ci-dessus cherche l’objet array (élément de tableau) de xyz. Comme il y a un élément de tableau qui correspond à xyz, il retournera vrai.

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

Maintenant, vous vous attendriez à ce que l’exemple ci-dessus retourne vrai, car chaque système Windows a un service W32Time, mais ce n’est pas le cas… pourquoi ? Eh bien parce que nous essayons de trouver un objet basé sur une seule propriété, name. L’opérateur -contains ne fonctionne cependant pas de cette manière. Il compare chaque propriété de l’objet et si toutes sont identiques, alors il renvoie True, sinon il renvoie false.

Dans l’exemple ci-dessus, nous comparons essentiellement un objet chaîne de caractères avec un objet System.ServiceProcess.ServiceController, ce qui ne va pas fonctionner.

Pour trouver un service avec la propriété name, nous devrions faire :

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

Bien que cela fonctionne, ce n’est peut-être pas le meilleur résultat car W32Time pourrait être la valeur d’une propriété dans un autre service et donc vous pourriez obtenir quelques faux positifs.

Pour éliminer le risque de faux positifs, je ferais personnellement quelque chose comme:

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

Enumérer tous les services de la collection et déterminer si chacune de leurs name propriétés est égale au terme de recherche est un moyen très précis de déterminer si le service particulier existe ou non et éliminera tous les faux positifs. Plus de code, mais une meilleure solution.

Pas de recherches?

En guise d’aparté, que se passe-t-il si vous voulez déterminer si quelque chose ne contient pas un terme de recherche particulier ?

Eh bien dans ce cas, il suffit d’utiliser -NotLike ou -NotContains de la même manière et dans les mêmes situations que vous utiliseriez -like et -contains.

Plus d’informations sur les opérateurs de comparaison

Si vous voulez en savoir plus sur tous les opérateurs de comparaison, alors consultez la page TechNet sur les opérateurs de comparaison.

Bien, j’espère que cela aidera à rendre les choses un peu plus claires sur le moment où il faut utiliser -Like et celui où il faut utiliser -Contains.

Laissez-moi savoir ce que vous en pensez ci-dessous…

Merci
Luca

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *