为啥类似 Powershell 的运算符与我的字符串不匹配?
Posted
技术标签:
【中文标题】为啥类似 Powershell 的运算符与我的字符串不匹配?【英文标题】:Why does the Powershell -like operator not match my string?为什么类似 Powershell 的运算符与我的字符串不匹配? 【发布时间】:2022-01-01 06:13:59 【问题描述】:这里我有 2 个变量:$repo
和 $growth_repo_name_list
。这是每个的输出:
> $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
是一个字符串,$growth_repo_name_list
是一个字符串数组:
> $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
没有隐藏字符,如下代码的输出所示:
> [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
即使我通过双引号将数组转换为扁平字符串,它仍然返回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
我在这里做错了什么?比较的结果应该是True
,因为$repo
包含的字符串在列表$growth_repo_name_list
中。提前感谢您的帮助。
【问题讨论】:
-like
需要通配符。你的目标是什么?测试$repo
是否可以在数组$growth_repo_name_list
中找到?那就试试$growth_repo_name_list -contains $repo
您确定不要$growth_repo_name_list -contains $repo
?
$repo = '*growth_medicare_consumertargetinganalyzer*'
?
【参考方案1】:
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
注意:
-in
执行的每个元素的相等比较默认情况下是不区分大小写的,就像 PowerShell 通常一样。
但是,您可以在运算符名称前加上 c
以使其区分大小写-敏感(在上面的示例中为-cin
。这适用于 all 字符串-处理运算符,包括下面讨论的那些。
至于你尝试了什么:
$repo -like $ph
($ph
是"$growth_repo_name_list"
) 比较的结果应该是$true
,因为字符串$repo
在列表$growth_repo_name_list
中
否:-like
,wildcard-matching operator,既不执行(直接)substring 匹配,也不支持与 RHS 字符串的 array 匹配。 p>
因此,直接的解决方法是反转操作数:
# *Array* of string inputs.
# Return those array elements that match the wildcard expression stored in $repo
$growth_repo_name_list -like $repo
这会将数组$growth_repo_name_list
的每个元素 与$repo
中的通配符表达式进行比较,并返回匹配元素的子数组。
如果子数组为空,则在Boolean 上下文(例如if ($growth_repo_name_list -like $repo) ...
)中使用返回数组转换为$false
,否则转换为$true
。
但是,$repo
在您的情况下只是一个字符串literal(它不包含诸如*
和?
等通配符元字符),因此没有理由使用-like
- 只需使用-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
相反,如果您想将$repo
的值匹配为数组元素的子字符串:
# *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 -like "*$repo*"
退一步:看来您只是想测试$repo
的值是否包含在存储在$growth_repo_name_list
中的数组中,即该值是否完整,等于(至少)数组的元素之一。
为此,PowerShell 提供了两个功能等效的运算符,-in
和 -contains
,它们的区别仅在于操作数顺序:
# 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
这些运算符直接返回布尔值($true
或 $false
)。
【讨论】:
【参考方案2】:所有比较都会产生$True
,你可能比较错了吗?
从about_Comparison_Operators中提取:
当输入是一个集合时,运算符返回集合中与表达式右侧值匹配的元素。如果集合中没有匹配项,则比较运算符返回一个空数组
$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
【讨论】:
以上是关于为啥类似 Powershell 的运算符与我的字符串不匹配?的主要内容,如果未能解决你的问题,请参考以下文章
Powershell:类似Haskell的$(apply)运算符?