234

Consider the following snippet:

"12-18" -Contains "-"

You’d think this evaluates to true, but it doesn't. This will evaluate to false instead. I’m not sure why this happens, but it does.

To avoid this, you can use this instead:

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

Now the expression will evaluate to true.

Why does the first code snippet behave like that? Is there something special about - that doesn't play nicely with -Contains? The documentation doesn't mention anything about it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tnw
  • 13,521
  • 15
  • 70
  • 111

4 Answers4

307

The -Contains operator doesn't do substring comparisons and the match must be on a complete string and is used to search collections.

From the documentation you linked to:

-Contains Description: Containment operator. Tells whether a collection of reference values includes a single test value.

In the example you provided you're working with a collection containing just one string item.

If you read the documentation you linked to you'll see an example that demonstrates this behaviour:

Examples:

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

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

I think what you want is the -Match operator:

"12-18" -Match "-"

Which returns True.

Important: As pointed out in the comments and in the linked documentation, it should be noted that the -Match operator uses regular expressions to perform text matching.

Kev
  • 118,037
  • 53
  • 300
  • 385
  • 26
    For completeness, while -Match may be a good match it uses regex. If one want a unambiguous string contains check one should do as the OP describes: `"12-18".Contains("-")` – 8DH Nov 30 '16 at 09:14
  • 5
    @8DH - very good catch :) . Having re-read the question I think I need to clarify the difference between the `Contains` powershell operator and the `.Contains()` _.NET_ `String` method. – Kev Nov 30 '16 at 11:08
  • 1
    As already mentioned in comment above, `-Match` uses regex. That means that the string parameter is a regex, not a normal string. For example, `"hello" -Match "."` will return true, because `"."` is a regex where a '.' will match any character. To check if a string contains a full stop: `"hello" -Match "\."` (returns false) – malla Jun 19 '19 at 13:47
  • 2
    This is certainly a "false friend"! :) The existence of "-contains" meaning "belonging to a list". – Raúl Salinas-Monteagudo Nov 14 '19 at 09:05
50

-Contains is actually a collection operator. It is true if the collection contains the object. It is not limited to strings.

-match and -imatch are regular expression string matchers, and set automatic variables to use with captures.

-like, -ilike are SQL-like matchers.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eris
  • 7,378
  • 1
  • 30
  • 45
35

You can use like:

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

Or split for contains:

"12-18" -split "" -contains "-"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Esperento57
  • 16,521
  • 3
  • 39
  • 45
2
  • like is best, or at least easiest.
  • match is used for regex comparisons.

Reference: About Comparison Operators

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maximojo
  • 315
  • 5
  • 17