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'

AD 组名称可能不需要需要转义,但重要的是要知道一般需要转义。

与 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

D. Vasya and Arrays

csu oj 1341 string and arrays

codeforces 620D Professor GukiZ and Two Arrays

[Agc001D] Arrays and Palindrome