数组和 -contains - 测试数组元素中的子字符串
Arrays and -contains - test for substrings in the elements of an array
我正在尝试过滤掉特定组中的用户。
我在变量中得到以下输出:
Group1
Group2
etc...
数组中保存的每一行一组。我试图只过滤掉一个特定的组。但是当我使用 -contains
时,它总是说 $false
,即使组在那里。
我的代码:
$group = get-aduser -identity name -properties memberof |
select-object -expandproperty memberof | %{ (get-adgroup $_).name }
$contains = $group -contains "string"
$contains
是 $false
即使数组的元素包含字符串...
我错过了什么?
答案是 -match
而不是 contains
。现在输出为真。
看起来 您的误解是您期望 PowerShell 的 -contains
operator 对 LHS 的元素执行 substring 匹配 数组。
相反,它 执行 equality 测试 - 正如 -eq
会 - 针对数组的元素 - 请参阅 this answer 了解详细信息。
为了对数组的元素执行文字子串匹配,使用:
# With non-literal search strings:
[bool] $contains = $group -match ([regex]::Escape($someString))
# With a string literal that doesn't contain regex metachars.,
# escaping isn't needed.
[bool] $contains = $group -match 'foo'
# With a string literal with metachars., you must individually \-escape them.
[bool] $contains = $group -match 'foo\.bar'
注:
上面显示了一种可靠的通用方法,可以确保使用 [regex]::Escape()
将您的搜索字符串视为 文字 值,这是必要的因为 -match
期望 regex (regular expression) 作为其 RHS(搜索模式).
转义并不总是必要的;具体来说,只有存在所谓的元字符(那些在正则表达式中具有特殊含义的字符,例如 .
)才需要它,并且当您使用字符串 literal 时,你可以选择直接 \
-escape 它们;例如,要搜索文字子字符串 a.b
,您可以传递 'a\.b'
.
- 有可能 AD 组名称不需要转义,但了解一般情况下的转义需求很重要。
与 PowerShell 中的所有运算符一样,默认情况下匹配是大小写 insensitive;使用 -cmatch
变体进行区分大小写的匹配。
上面约束的[bool]
类型是用来保证-match
运算的结果转换为布尔值:
- 虽然
-match
直接 returns 具有 标量的布尔值 (非数组)LHS,具有 array LHS 它充当 过滤器,returns 匹配数组元素 而不是 ;在布尔上下文中解释,例如在 if
条件中,通常仍会给出预期结果,因为非空数组被解释为 $true
,而空数组被解释为 $false
;再次强调,但是了解其中的区别很重要。
这在实践中很少会成为性能问题,但值得注意的是 -match
,由于作为数组的过滤器,总是匹配 all array elements - 一旦找到 first 匹配,它就不会停止,-contains
和-in
运营商会。
从好的方面来说,您可以使用-match
来获取匹配元素本身。
对 -contains
执行 子串 匹配的错误期望可能是由于 与名称相似但不相关的 String.Contains()
[混淆了] method,它确实执行文字substring匹配;例如,'foo'.Contains('o')
产生 $true
.
另请注意 .Contains()
区分大小写 - invariably in Windows PowerShell,在 PowerShell (Core) 7+.
中默认[=118=]
PowerShell 有 no 运算符用于 literal 子字符串匹配。
但是,您可以将 PowerShell 的通用数组过滤功能与 .Contains()
字符串方法结合使用 - 但请注意,这通常比 -match
方法的性能(可能差很多)。
一个合理的替代方案是使用 PSv4+ .Where()
数组方法,如下所示:
# Note: Substring search is case-sensitive here.
[bool] $contains = $group.Where({ $_.Contains("string") }, 'First')
从好的方面来说,一旦找到第一个匹配项,此方法就会停止匹配。
我正在尝试过滤掉特定组中的用户。
我在变量中得到以下输出:
Group1
Group2
etc...
数组中保存的每一行一组。我试图只过滤掉一个特定的组。但是当我使用 -contains
时,它总是说 $false
,即使组在那里。
我的代码:
$group = get-aduser -identity name -properties memberof |
select-object -expandproperty memberof | %{ (get-adgroup $_).name }
$contains = $group -contains "string"
$contains
是 $false
即使数组的元素包含字符串...
我错过了什么?
答案是 -match
而不是 contains
。现在输出为真。
看起来 您的误解是您期望 PowerShell 的 -contains
operator 对 LHS 的元素执行 substring 匹配 数组。
相反,它 执行 equality 测试 - 正如 -eq
会 - 针对数组的元素 - 请参阅 this answer 了解详细信息。
为了对数组的元素执行文字子串匹配,使用:
# With non-literal search strings:
[bool] $contains = $group -match ([regex]::Escape($someString))
# With a string literal that doesn't contain regex metachars.,
# escaping isn't needed.
[bool] $contains = $group -match 'foo'
# With a string literal with metachars., you must individually \-escape them.
[bool] $contains = $group -match 'foo\.bar'
注:
上面显示了一种可靠的通用方法,可以确保使用
[regex]::Escape()
将您的搜索字符串视为 文字 值,这是必要的因为-match
期望 regex (regular expression) 作为其 RHS(搜索模式).转义并不总是必要的;具体来说,只有存在所谓的元字符(那些在正则表达式中具有特殊含义的字符,例如
.
)才需要它,并且当您使用字符串 literal 时,你可以选择直接\
-escape 它们;例如,要搜索文字子字符串a.b
,您可以传递'a\.b'
.- 有可能 AD 组名称不需要转义,但了解一般情况下的转义需求很重要。
与 PowerShell 中的所有运算符一样,默认情况下匹配是大小写 insensitive;使用
-cmatch
变体进行区分大小写的匹配。上面约束的
[bool]
类型是用来保证-match
运算的结果转换为布尔值:- 虽然
-match
直接 returns 具有 标量的布尔值 (非数组)LHS,具有 array LHS 它充当 过滤器,returns 匹配数组元素 而不是 ;在布尔上下文中解释,例如在if
条件中,通常仍会给出预期结果,因为非空数组被解释为$true
,而空数组被解释为$false
;再次强调,但是了解其中的区别很重要。
- 虽然
这在实践中很少会成为性能问题,但值得注意的是
-match
,由于作为数组的过滤器,总是匹配 all array elements - 一旦找到 first 匹配,它就不会停止,-contains
和-in
运营商会。从好的方面来说,您可以使用
-match
来获取匹配元素本身。
对 -contains
执行 子串 匹配的错误期望可能是由于 与名称相似但不相关的 String.Contains()
[混淆了] method,它确实执行文字substring匹配;例如,'foo'.Contains('o')
产生 $true
.
另请注意 .Contains()
区分大小写 - invariably in Windows PowerShell,在 PowerShell (Core) 7+.
PowerShell 有 no 运算符用于 literal 子字符串匹配。
但是,您可以将 PowerShell 的通用数组过滤功能与 .Contains()
字符串方法结合使用 - 但请注意,这通常比 -match
方法的性能(可能差很多)。
一个合理的替代方案是使用 PSv4+ .Where()
数组方法,如下所示:
# Note: Substring search is case-sensitive here.
[bool] $contains = $group.Where({ $_.Contains("string") }, 'First')
从好的方面来说,一旦找到第一个匹配项,此方法就会停止匹配。