Home > Mobile >  Why does the Powershell -like operator not match my string?
Why does the Powershell -like operator not match my string?

Time:11-23

Here I have 2 variables: $repo and $growth_repo_name_list. Here is the output of each:

> $repo
growth_medicare_consumertargetinganalyzer

> $growth_repo_name_list
2021.2
growth_ifp_consumersummary_v2
growth_ifp_consumertargetinganalyzer
growth_medicare_all_usconsumerattributes
growth_medicare_consumersummary_v2
growth_medicare_consumertargetinganalyzer
growth_medicare_growthopportunityindex
growth_medicare_ifp_all_usconsumerattributes
growth_medicare_ntmtargetinganalyzer
marketintel_medicare_historicalenrollmentanalyzer
marketintel_medicare_planbenefits
memberintel_ifp_aepoepreporting_v2
memberintel_ifp_memberreporting_v2
memberintel_medicaid_memberreporting_v2
memberintel_medicare_aepoepreporting_v2
memberintel_medicare_memberreporting_v2

$repo is a string, and $growth_repo_name_list is an Array of strings:

> $repo.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

> $growth_repo_name_list.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

$repo has no hidden characters as shown by the output of the following code:

> [System.Text.Encoding]::UTF8.GetBytes($repo)
103
114
111
119
116
104
95
109
101
100
105
99
97
114
101
95
99
111
110
115
117
109
101
114
116
97
114
103
101
116
105
110
103
97
110
97
108
121
122
101
114

> [System.Text.Encoding]::UTF8.GetBytes($growth_repo_name_list[5])
103
114
111
119
116
104
95
109
101
100
105
99
97
114
101
95
99
111
110
115
117
109
101
114
116
97
114
103
101
116
105
110
103
97
110
97
108
121
122
101
114

Even when I cast the Array into a flat string via double quotes it still returns False:

> "$growth_repo_name_list"
2021.2 growth_ifp_consumersummary_v2 growth_ifp_consumertargetinganalyzer growth_medicare_all_usconsumerattributes growth_medicare_consumersummary_v2 growth_medicare_consumertargetinganalyzer growth_medicare_growthopportunityindex growth_medicare_ifp_all_usconsumerattributes growth_medicare_ntmtargetinganalyzer marketintel_medicare_historicalenrollmentanalyzer marketintel_medicare_planbenefits memberintel_ifp_aepoepreporting_v2 memberintel_ifp_memberreporting_v2 memberintel_medicaid_memberreporting_v2 memberintel_medicare_aepoepreporting_v2 memberintel_medicare_memberreporting_v2

> $ph = "$growth_repo_name_list"

> $repo -like $ph
False

> $ph.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

What am I doing wrong here? The result of the comparison should be True since the string $repo contains is in the list $growth_repo_name_list. Thanks for the help in advance.

CodePudding user response:

All comparisons will yield $True, you might be comparing them wrong?

Extract from about_Comparison_Operators:

When the input is a collection, the operator returns the elements of the collection that match the right-hand value of the expression. If there are no matches in the collection, comparison operators return an empty array

$repo = 'growth_medicare_consumertargetinganalyzer'

$growth_repo_name_list = @(
    '2021.2'
    'growth_ifp_consumersummary_v2'
    'growth_ifp_consumertargetinganalyzer'
    'growth_medicare_all_usconsumerattributes'
    'growth_medicare_consumersummary_v2'
    'growth_medicare_consumertargetinganalyzer'
    'growth_medicare_growthopportunityindex'
    'growth_medicare_ifp_all_usconsumerattributes'
    'growth_medicare_ntmtargetinganalyzer'
    'marketintel_medicare_historicalenrollmentanalyzer'
    'marketintel_medicare_planbenefits'
    'memberintel_ifp_aepoepreporting_v2'
    'memberintel_ifp_memberreporting_v2'
    'memberintel_medicaid_memberreporting_v2'
    'memberintel_medicare_aepoepreporting_v2'
    'memberintel_medicare_memberreporting_v2'
)

[bool]($growth_repo_name_list -like $repo)  # => True
$repo -in $growth_repo_name_list            # => True
$growth_repo_name_list -contains $repo      # => True
[bool]($growth_repo_name_list -match $repo) # => True
$growth_repo_name_list.Contains($repo)      # => True

CodePudding user response:

tl;dr

# Is the value of $repo equal to at least one element of array $growth_repo_name_list?
$repo -in $growth_repo_name_list

Note:

  • The per-element equality comparison that -in performs is case-insensitive by default, as PowerShell generally is.

  • However, you can prefix the operator name with c to make it case-sensitive (-cin in the example above. This applies to all string-processing operator, including the ones discussed below.


As for what you tried:

$repo -like $ph ($ph being "$growth_repo_name_list")
The result of the comparison should be $true since the string $repo is in the list $growth_repo_name_list

No: -like, the wildcard-matching operator, neither performs (direct) substring matching, nor does it support matching against an array of RHS strings.

  • Instead, it compares the LHS - a single input string or an array of input string(s) - to a single wildcard expression on the RHS.
  • If you accidentally use an array as the RHS, the array is stringified, by concatenating the (stringified) array elements with a single space between them to form a single string - this will rarely be helpful.

Therefore, the immediate fix is to reverse the operands:

# *Array* of string inputs. 
# Return those array elements that match the wildcard expression stored in $repo
$growth_repo_name_list -like $repo

This compares each element of array $growth_repo_name_list to the wildcard expression in $repo, and returns the sub-array of matching elements.

Using the return array in a Boolean context (e.g. if ($growth_repo_name_list -like $repo) ...) translates to $false if the sub-array is empty, and $true otherwise.

However, $repo is just a string literal in your case (it contains no wildcard metacharacters such as * and ?), so there is no reason to use -like - just use -eq:

# *Array* of string inputs. 
# Return those array elements that are case-insensitively equal to the
# string stored in $repo.
$growth_repo_name_list -eq $repo

Conversely, if you wanted to match the value of $repo as a substring of the array elements:

# *Array* of string inputs. 
# Return those array elements that case-insensitively contain the
# string stored in $repo as a substring (or in full).
$growth_repo_name_list -lik "*$repo*"

Taking a step back: It seems that you simply want to test whether the value of $repo is contained in the array stored in $growth_repo_name_list, i.e. if the value is, in full, equal to (at least) one of the elements of the array.

For that, PowerShell offers two functionally equivalent operators, -in and -contains, which differ only by operand order:

# Is the value of $repo equal to at least one element of array $growth_repo_name_list?
$repo -in $growth_repo_name_list

# Ditto, operands reversed.
$growth_repo_name_list -contains $repo

These operators directly return a Boolean value ($true or $false).

  • Related