Arrays 和 -contains - 测试数组元素中的子字符串

Arrays and -contains - test for substrings in the elements of an array

提问人:seyo -IV 提问时间:4/9/2019 最后编辑:mklement0seyo -IV 更新时间:11/17/2023 访问量:4212

问:

我正在尝试过滤掉特定组中的用户。

我在变量中得到了以下输出: 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

我错过了什么?

PowerShell 子字符串 匹配 包含

评论

1赞 Olaf 4/9/2019
它实际上按预期工作。你唯一需要照顾的事情......“字符串”必须完全匹配!;-)

答:

0赞 seyo -IV 4/9/2019 #1

答案是.现在输出为 true。-matchcontains

4赞 mklement0 4/10/2019 #2

看起来你的误解是你希望 PowerShell 的 -contains 运算符对 LHS 数组的元素执行子字符串匹配
取而代之的是,它对数组的元素执行相等性测试 - 有关详细信息,请参阅此答案
-eq

为了数组的元素执行文字子字符串匹配,如果需要,请使用
带有转义的 -match 运算符

# 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'

注意:

  • 另一种方法是使用基于通配符的类似通配运算符,但默认情况下执行字符串匹配,因此需要将搜索词括起来以进行子字符串匹配;例如:*...*

    [bool] $contains = $group -like '*foo*'
    
    • 以下几点也同样适用,不同之处在于 (a) 不太可能需要转义,因为只有 、、/ 和是元字符,以及 (b) 字符-个人转义需要和编程转义需要 [WildcardPattern]::Escape()-like*?[]``
  • 上面显示了一种强大的通用方法,可以确保使用 [regex]::Escape() 将搜索字符串视为文本值(逐字),这是必需的,因为 -match 需要正则表达式(正则表达式)作为其 RHS(搜索模式)。

  • 逃避并不总是必要的;具体来说,只有所谓的元字符(在正则表达式中具有特殊含义的元字符,例如)的存在才需要它,并且当您使用字符串文字时,您可以选择直接转义它们;例如,要搜索文字子字符串,您可以传递 ..\a.b'a\.b'

    • AD 组名称可能不需要转义,但重要的是要了解一般情况下对它的需求。
  • 与 PowerShell 中的所有运算符一样,默认情况下,匹配不区分大小写;使用变体进行区分大小写的匹配。-cmatch

  • 上面的 [bool] 类型约束用于确保将操作结果转换为布尔值:-match

    • 虽然 -match 直接返回带有标量(非数组)LHS 的布尔值,但使用数组 LHS 时,它充当过滤器,并返回匹配的数组元素;在布尔上下文中解释,例如在条件上下文中,通常仍然给出预期的结果,因为非空数组被解释为 ,而空数组被解释为 ;然而,同样,了解其中的区别很重要。if$true$false
  • 在实践中,这很少会成为性能问题,但值得注意的是-match 由于充当数组的过滤器,因此始终与所有数组元素匹配 - 一旦找到第一个匹配项,它就不会停止,就像 and 运算符所做的那样。-contains-in

  • 从好的方面来说,您可以使用它来获取匹配的元素本身。-match


执行子字符串匹配的错误期望可能是由于与名称相似但不相关的 String.Contains() 方法混淆而引起的,该方法确实执行字面子字符串匹配;例如,收益率 .
另请注意 .Contains() 区分大小写 - 在 Windows PowerShell始终区分大小写,在 PowerShell (Core) 7+默认为。
-contains'foo'.Contains('o')$true

PowerShell 没有用于文本子字符串匹配的运算符。

但是,可以将 PowerShell 的通用数组筛选功能与字符串方法结合使用,但请注意,这通常比该方法执行(可能差得多)。.Contains()-match

一个性能合理的替代方法是使用 PSv4+ 数组方法,如下所示:.Where()

# Note: Substring search is case-sensitive here.
[bool] $contains = $group.Where({ $_.Contains("string") }, 'First')

从好的方面来说,一旦找到第一个匹配项,此方法就会停止匹配。