PowerShell et l'opérateur -contains

143

Considérez l'extrait de code suivant:

"12-18" -Contains "-"

Vous pensez que cela vaut true, mais ce n'est pas le cas. Cela évaluera à la falseplace. Je ne sais pas pourquoi cela se produit, mais c'est le cas.

Pour éviter cela, vous pouvez utiliser ceci à la place:

"12-18".Contains("-")

Maintenant, l'expression sera évaluée à vrai.

Pourquoi le premier extrait de code se comporte-t-il comme ça? y a-t-il quelque chose de spécial -qui ne joue pas bien avec -Contains? La documentation n'en mentionne rien.

tnw
la source

Réponses:

197

L' -Containsopérateur ne fait pas de comparaisons de sous-chaînes et la correspondance doit être sur une chaîne complète et est utilisée pour rechercher des collections.

De la documentation que vous avez liée à:

-Contient Description: Opérateur de confinement. Indique si une collection de valeurs de référence comprend une seule valeur de test.

Dans l'exemple que vous avez fourni, vous travaillez avec une collection contenant un seul élément de chaîne.

Si vous lisez la documentation que vous avez liée, vous verrez un exemple illustrant ce comportement:

Exemples:

PS C:\> "abc", "def" -Contains "def"
True

PS C:\> "Windows", "PowerShell" -Contains "Shell"
False  #Not an exact match

Je pense que ce que vous voulez, c'est l' -Matchopérateur:

"12-18" -Match "-"

Qui revient True.

Important: comme indiqué dans les commentaires et dans la documentation liée , il convient de noter que l' -Matchopérateur utilise des expressions régulières pour effectuer une correspondance de texte.

Kev
la source
14
Par souci d'exhaustivité, alors que -Match peut être une bonne correspondance, il utilise regex. Si l'on veut qu'une chaîne non ambiguë contienne une vérification, on doit faire ce que l'OP décrit:"12-18".Contains("-")
8DH
4
@ 8DH - très bonne prise :). Après avoir relu la question, je pense que je dois clarifier la différence entre l' Containsopérateur PowerShell et la méthode .Contains() .NET String .
Kev
1
Comme déjà mentionné dans le commentaire ci-dessus, -Matchutilise regex. Cela signifie que le paramètre de chaîne est une expression régulière, pas une chaîne normale. Par exemple, "hello" -Match "."retournera true, car "."est une expression régulière où un '.' correspondra à n'importe quel caractère. Pour vérifier si une chaîne contient un point: "hello" -Match "\."(renvoie false)
malla
1
@malla - bon point, j'ai édité une note à ce sujet. Merci.
Kev
C'est certainement un "faux ami"! :) L'existence de "-contains" signifiant "appartenant à une liste".
Raúl Salinas-Monteagudo
38

-Containsest en fait un opérateur de collecte. C'est vrai si la collection contient l'objet. Il n'est pas limité aux chaînes.

-match et -imatch correspondent à des chaînes d'expressions régulières et définissent des variables automatiques à utiliser avec les captures.

-like, -ilikesont des correspondants de type SQL.

Eris
la source
13

Vous pouvez utiliser like:

"12-18" -like "*-*"

Ou splitpour contains:

"12-18" -split "" -contains "-"
Esperento57
la source