数组和-包含-测试数组元素中的子字符串 [英] Arrays and -contains - test for substrings in the elements of an array
问题描述
我正在尝试过滤掉特定组中的用户.
I am trying to filter out users that are in a specific group.
我在变量中得到以下输出:
Group1
Group2
etc...
I got the following output in a variable:
Group1
Group2
etc...
保存在数组中的每行的一组.我试图只过滤出一个特定的组.但是,当我使用-contains
时,它总是说$false
,即使该组在那里.
One group for each line saved in an array. Im trying to filter out only one specific group. But when I use -contains
it always says $false
, even tho the group is there.
我的代码:
$group = get-aduser -identity name -properties memberof |
select-object -expandproperty memberof | %{ (get-adgroup $_).name }
$contains = $group -contains "string"
即使数组的元素包含字符串...,
$contains
仍为$false
.
$contains
is $false
even if the array has elements that contain the string...
我想念什么?
推荐答案
您的误解是您期望PowerShell的此答案以获取详细信息.
It looks like your misconception was that you expected PowerShell's -contains
operator to perform substring matching against the elements of the LHS array.
Instead, it performs equality tests - as -eq
would - against the array's elements - see this answer for details.
要针对数组的元素 执行文字子字符串匹配,请使用:
# 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()
将搜索字符串视为 literal 值,这是必需的,因为-match
期望输入一个 regex (常规表达式)作为其RHS(搜索模式).
The above shows a robust, generic way of ensuring that your search string is treated as a literal value using
[regex]::Escape()
, which is necessary because-match
expects a regex (regular expression) as its RHS (the search pattern).
转义并非总是必要的;具体来说,只有存在所谓的元字符(在正则表达式中具有特殊含义的字符,例如.
)才需要它,并且在使用字符串 literal 时,您可以选择直接\
-逃脱它们;例如,要搜索文字子字符串a.b
,您可以传递'a\.b'
.
Escaping isn't always necessary; specifically, only the presence of so-called metacharacters (those with special meaning in a regex, such as .
) requires it, and when you're using a string literal, you can opt to directly \
-escape them; e.g., to search for literal substring a.b
, you can pass 'a\.b'
.
- 有可能AD组名不需要转义,但重要的是要意识到一般的需要.
与PowerShell中的所有运算符一样,默认情况下,匹配不区分大小写 ;使用-cmatch
变体进行区分大小写的匹配.
As with all operators in PowerShell, by default the matching is case-insensitive; use the -cmatch
variant for case-sensitive matching.
上面约束的[bool]
类型用于确保-match
操作的结果转换为布尔值:
The [bool]
type constrained above is used to ensure that the result of the -match
operation is converted to a Boolean:
-
-match
直接返回带有标量(非数组)LHS的布尔值,而带有 array LHS的布尔值则充当过滤器,并返回匹配数组元素 ;在布尔上下文中(例如在if
条件中)解释,通常仍能得到预期的结果,因为非空数组被解释为$true
,而空数组则被解释为$false
;再次,但是重要的是要知道区别.
- While
-match
directly returns a Boolean with a scalar (non-array) LHS, with an array LHS it acts as a filter, and returns the matching array elements instead; interpreted in a Boolean context, such as in anif
conditional, that usually still gives the expected result, because a non-empty array is interpreted as$true
, whereas an empty one as$false
; again, however it's important to know the difference.
这在实践中很少会涉及性能,但是值得注意的是, -match
由于用作数组的过滤器,总是与 all 数组匹配元素-一旦找到 first 匹配项,它就不会停止,就像-contains
和-in
运算符一样.
This will rarely be a performance concern in practice, but it is worth noting that -match
, due to acting as a filter with arrays, always matches against all array elements - it doesn't stop once the first match is found, the way that the -contains
and -in
operators do.
- 从正面看,您可以使用
-match
本身获取匹配的元素.
- On the plus side, you can use
-match
to obtain the matching elements themselves.
对-contains
执行 substring 匹配的错误期望可能是由于与名称相似但无关的
The mistaken expectation of -contains
performing substring matching may have arisen from confusion with the similarly named, but unrelated String.Contains()
method, which indeed performs literal substring matching; e.g., 'foo'.Contains('o')
yields $true
. Also note that .Contains()
is case-sensitive by default.
PowerShell具有 no 运算符,用于 literal 子字符串匹配.
PowerShell has no operator for literal substring matching.
但是,您可以将PowerShell的通用数组过滤功能与.Contains()
字符串方法结合使用-但请注意,这通常会(可能会)比-match
方法更糟糕.
However, you could combine PowerShell's generic array-filtering features with the .Contains()
string method - but note that this will typically perform (potentially much) worse than the -match
approach.
合理执行的替代方法是使用PSv4 + .Where()
数组方法,如下所示:
A reasonably performant alternative is to use the PSv4+ .Where()
array method as follows:
# Note: Substring search is case-sensitive here.
[bool] $contains = $group.Where({ $_.Contains("string") }, 'First')
从好的方面来说,一旦找到第一个匹配项,此方法就会停止匹配.
On the plus side, this approach stops matching once the first match is found.
这篇关于数组和-包含-测试数组元素中的子字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!