【问题标题】:Filter for one or more elements in an array过滤数组中的一个或多个元素
【发布时间】:2017-02-07 03:06:57
【问题描述】:

基本上我想在 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}

【问题讨论】:

    标签: powershell


    【解决方案1】:

    最方便的解决方案是使用retrieve-all -Filter 参数(-Filter *),然后通过管道传递给Where-Object cmdlet,这样可以使用-in 运算符,用于测试数组包含 (PSv3+):

    Get-ADOrganizationalUnit -SearchBase "OU=myOU,DC=domain,DC=biz" -Filter * |
      Where-Object name -in $Strings
    

    需要使用单独的 Where-Object 调用,因为 AD cmdlet 的 -Filter 参数不支持 -in 运算符 - 重要的是要了解它是目标 cmdlet,而不是 PowerShell,它解释了-Filter 参数。

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

    【讨论】:

      【解决方案2】:

      tl;dr

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

      • 使用带有Where-Object 的管道时 一个选项,如Martin Brandl's answer - 让PowerShell 进行过滤稍后 em>,在未经过滤的检索之后 - 它会比使用 -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 参数由 target cmdlet 解释,而不是 PowerShell

      • 过滤器的语法由目标 cmdlet 规定,该语法可能与 PowerShell 类似,并且可能因 cmdlet(组)而异。

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

            1234563 /p>
        • 相比之下,与文件系统提供程序相关的 cmdlet(例如 Get-ChildItem)仅支持单个通配符表达式作为 -Filter 参数,例如 *.txt,并且特定的通配符表达式方言与 PowerShell 的不同自己的,甚至是平台相关的 - 请参阅我的this answer

    • 尽管存在局限性并且缺乏直接的 PowerShell 集成,但过滤器有一个重要优势:它们在源过滤对象,这使得检索更快、更有效 strong> 与 unfiltered 相比,检索通过管道传输到 PowerShell 的 Where-Object cmdlet 以供稍后过滤。

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

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

      • 虽然传递一个脚本块可能看起来很方便,尤其是为了简化引用,但它有陷阱,因为脚本块总是被转换为[string]

        • 脚本块的字符串表示只是开头{ 和结尾} 之间的字符串,原样,包括空格。例如,这意味着脚本块 { name -eq $var } 变成了一个字符串,其 literal 内容为  name -eq $var  - 换句话说:$var 未插入。 p>

        • 虽然AD cmdlet 似乎确实应用了一轮额外的字符串插值[1] 到结果文字 - 例如 Get-ChildItem 不是这样 - 即使这样也有缺陷:

          • 诸如{ name -eq $someObj.Name } 之类的脚本块将工作,因为访问变量的属性直接在插值中工作字符串(使用$(...),需要子表达式运算符 - 背景见我的this answer)。

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

        • 这可能会给人一种错误的印象,即支持正则 PowerShell 表达式。


    • [1] 这是我从观察到的行为中推断出来的。如果您知道更多/知道此推论不正确,请告诉我们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-26
        • 1970-01-01
        • 2015-11-09
        • 1970-01-01
        • 2018-03-07
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        相关资源
        最近更新 更多