为啥类似 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>

相反,它将 LHS(单个输入字符串或输入字符串数组)与 RHS 上的 单个wildcard expression 进行比较。 如果您不小心将 array 用作 RHS,则该数组是 stringified,通过将(字符串化的)数组元素与它们之间的单个空格连接起来形成一个字符串 - 这很少有用。

因此,直接的解决方法是反转操作数

# *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 不处理这个 $?正确退出代码?

Powershell:类似Haskell的$(apply)运算符?

为啥在添加 powershell 字符串和数组时操作数的顺序很重要? [复制]

(19)Powershell字符串合并运算符

(18)Powershell中的字符串拆分运算符

PowerShell初级篇●Powershell条件判断