Arrays and -contains - 测试数组元素中的子字符串
Posted
技术标签:
【中文标题】Arrays and -contains - 测试数组元素中的子字符串【英文标题】:Arrays and -contains - test for substrings in the elements of an array 【发布时间】:2019-08-30 20:32:59 【问题描述】:我正在尝试过滤掉特定组中的用户。
我在一个变量中得到以下输出:
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
,即使数组中的元素包含该字符串...
我错过了什么?
【问题讨论】:
它实际上按预期工作。您唯一需要注意的事情......“字符串”必须是完全匹配的! ;-) 【参考方案1】:看起来您的误解是您希望 PowerShell 的 -contains
operator 对 LHS 数组的元素执行 substring 匹配。
相反,它执行平等测试 - 正如-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
需要一个正则表达式 (regular expression) 作为其 RHS(搜索模式)。
转义并不总是必要的;具体来说,只有所谓的元字符(在正则表达式中具有特殊含义的元字符,例如 .
)才需要它,并且当您使用字符串 literal 时,您可以选择直接\
-逃脱他们;例如,要搜索文字子字符串a.b
,您可以传递'a\.b'
。
与 PowerShell 中的所有运算符一样,默认情况下匹配是不区分大小写的;使用-cmatch
变体进行区分大小写的匹配。
上面约束的[bool]
类型用于确保-match
操作的结果被转换为布尔值:
-match
直接返回带有标量(非数组)LHS 的布尔值,但带有数组 LHS 的它充当过滤器,并返回匹配的数组元素而不是;在布尔上下文中解释,例如在if
条件中,通常仍然给出预期结果,因为非空数组被解释为$true
,而空数组被解释为$false
;再次强调,但重要的是要知道其中的区别。
这在实践中很少会成为性能问题,但值得注意的是,-match
,由于充当数组的过滤器,总是匹配 所有 数组元素 - 一旦找到 first 匹配,它就不会停止,就像 -contains
和 -in
运算符所做的那样。
从好的方面来说,您可以使用-match
自己获取匹配的元素。
错误期望-contains
执行子字符串 匹配可能是由于混淆了名称相似但不相关的String.Contains()
方法 ,它确实执行了文字 substring 匹配;例如,'foo'.Contains('o')
产生 $true
。
另请注意,.Contains()
区分大小写 - 在 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')
从好的方面来说,一旦找到第一个匹配项,这种方法就会停止匹配。
【讨论】:
【参考方案2】:答案是-match
插入contains
。现在输出为真。
【讨论】:
如果您在问题中显示了示例输入和预期输出,那么您对-contains
工作原理的误解从一开始就很明显。虽然使用 -match
进行数组元素 substring 匹配通常有效,但存在许多陷阱和微妙之处,如我的回答中所述(否决票不是我的)。以上是关于Arrays and -contains - 测试数组元素中的子字符串的主要内容,如果未能解决你的问题,请参考以下文章
「题解」CF620D Professor GukiZ and Two Arrays
微带天线读书: Microstrip Antennas: The Analysis and Design of Microstrip Antennas and Arrays