过滤数组中的一个或多个元素

时间:2017-02-01 13:55:48

标签: powershell

基本上我想在PowerShell中这样做。

Get-ADOrganizationalUnit -SearchBase "OU=myOU,DC=domain,DC=biz" -Filter {name -eq "_Computer" -or name -eq "_Devices"}

但是,我想在数组中声明字符串,因为我更需要它们。

很容易说,我想这样做。但是,当然,它不起作用!

$Strings = @("_Computer", "_Devices")

Get-ADOrganizationalUnit -SearchBase "OU=myOU,DC=domain,DC=biz" -Filter {name -eq $Strings}

2 个答案:

答案 0 :(得分:2)

最方便的解决方案是使用全部检索-Filter参数(-Filter *)然后通过管道传输到{{1} } cmdlet,它允许使用Where-Object运算符来测试数组包含(PSv3 +):

-in

需要使用单独的Get-ADOrganizationalUnit -SearchBase "OU=myOU,DC=domain,DC=biz" -Filter * | Where-Object name -in $Strings 来电,因为AD cmdlet' Where-Object参数不支持-Filter运算符 - 了解解释-in参数的目标cmdlet而非PowerShell非常重要。

但是,请注意,此便利性具有严重的性能影响 :使用-Filter参数通常比将未过滤的检索与未过滤检索相结合更快,更有效稍后在PowerShell 中过滤,因为-Filter在源过滤 - 请参阅this answer了解基于-Filter的解决方案和背景信息。

答案 1 :(得分:2)

<强> TL;博士

  • AD cmdlet的-Filter参数不支持-in(数组包含)运算符,因此-Filter { name -in $Strings } 不是选项 - 见about_ActiveDirectory_Filter

  • 使用Where-Object 的管道是一个选项,如Martin Brandl's answer - 让 PowerShell 进行过滤之后,在未经过滤的检索之后 - 它将比使用-Filter慢得多且效率低。

  • 要使用-Filter,请将过滤器合成为字符串(事实上, ),以模拟-in来自与-eq加入的-or个表达式数组:

# Sample organizational unit names.
$Strings = @("_Computer", "_Devices")

# Construct the filter string; with the sample input, this yields a single
# string with the following content:
#     Name -eq "_Computer" -or Name -eq "_Devices"
$Filter = ($Strings | ForEach-Object { "Name -eq `"$_`"" }) -join ' -or '

#`# Pass the filter string to the AD cmdlet.
Get-ADOrganizationalUnit -SearchBase "OU=myOU,DC=domain,DC=biz" -Filter $Filter

背景资料:

  • -Filter参数由目标cmdlet 解释,而不是 PowerShell

  • 过滤器的语法由目标cmdlet 规定,该语法可能是也可能不是PowerShell- ,如,并且可以从cmdlet到cmdlet不等(组)。

    • 您必须查阅目标cmdlet的文档以了解要使用的语法 - 不要假设您可以传递包含PowerShell表达式的任意脚本块;例如:

      • 诸如Get-ADOrganizationalUnit之类的AD cmdlet支持非常有限的特定于域的表达式语言,该语言使用PowerShell- 之类的语法,但有许多怪癖和异常 - 请参阅{{3 }}

      • 相比之下,与Get-ChildItem等文件系统提供程序相关的cmdlet仅支持单个通配符表达式作为-Filter参数,例如*.txt,以及特定的通配符 - 表达式方言与PowerShell自身甚至平台相关的不同 - 请参阅我的about_ActiveDirectory_Filter

  • 尽管存在局限性且缺乏直接的PowerShell集成,但过滤器具有一个重要优势:它们在源过滤对象,这样可以更快,更有效地检索 strong>与未经过滤的检索相比,通过管道传输到PowerShell的Where-Object cmdlet进行以后过滤。

  • 过滤器在技术上是字符串[string]个实例)。

    • 最好构造并将作为字符串传递给它们,而不是PowerShell 脚本块

    • 虽然传递脚本块似乎很方便,尤其是为了简化引用,它有陷阱,因为脚本块总是被转换为{{1 }}:

      • 脚本块的字符串表示形式只是开头[string]和结束{之间的字符串,原样,包括空格。例如,这意味着脚本块}变为文字内容为{ name -eq $var }的字符串 - 换句话说: name -eq $var  未插值< / EM>

      • AD cmdlet时,似乎确实应用了一轮额外的字符串插值 [1] 得到的文字 - 例如$var不正确 - 即使有陷阱:

        • Get-ChildItem等脚本块将工作,因为访问变量的属性 直接工作插值字符串(使用{ name -eq $someObj.Name },子表达式运算符是必需的 - 请参阅我的this answer作为背景信息。

        • 使用隐式远程处理,这一额外的字符串插值可能会发生远程,其中本地变量无法访问。

      • 可能会给人以错误的印象,即支持常规的PowerShell表达式。

[1]这是我从观察到的行为中推断的。请告诉我们您是否了解更多/知道此推断是不正确的。