【问题标题】:-contains or -match several values- 包含或 - 匹配多个值
【发布时间】:2018-03-08 22:23:51
【问题描述】:

我必须通过某些字符串过滤我的结果,并尝试使用 -match-contains 来实现。

-match 如果我只有一个要过滤的值,但不适用于数组。

-contains 既不适用于一个字符串,也不适用于字符串数组。

为什么它不能使用多个值?尤其是-contains。或者有其他简单的方法可以解决吗?

$Folder = 'C:\Test'

$filterArray =  @('2017-05', '2017-08')
$filter =  '2017-05'

## test with -MATCH

## working with one match string
Get-ChildItem -Path $Folder -Recurse -Include *.txt |
    Where { $_.FullName -match $filter } |
    ForEach-Object { $_.FullName }
## NOT working with match string array - no results
Get-ChildItem -Path $Folder -Recurse -Include *.txt |
    Where { $_.FullName -match $filterArray } |
    ForEach-Object { $_.FullName }

## test with -CONTAINS
## NOT working with one contains string - no results
Get-ChildItem -Path $Folder -Recurse -Include *.txt |
    Where { $_.FullName -contains $filter } |
    ForEach-Object { $_.FullName }
## NOT working with contains string array- no results
Get-ChildItem -Path $Folder -Recurse -Include *.txt |
    Where { $_.FullName -contains $filterArray } |
    ForEach-Object { $_.FullName }

【问题讨论】:

标签: powershell powershell-3.0


【解决方案1】:

为什么它不能使用多个值?

因为这些运算符旨在针对单个参数进行测试,简单明了。

在单个操作中匹配多个参数的能力会引出一个问题:“输入是否需要满足 allany 的参数条件”?


如果您想测试与 任何 正则表达式模式数组的匹配,您可以使用非捕获组从它们构造单个模式,如下所示:

$filterPattern = '(?:{0})' -f ($filterArray -join '|')
Get-ChildItem -Path $Folder -Recurse -Include *.txt | Where {$_.FullName -match $filterPattern} | ForEach-Object{ $_.FullName }

您也可以完全删除 Where-ObjectForEach-Object 循环,因为 PowerShell 3.0 支持属性枚举:

(Get-ChildItem -Path $Folder -Recurse -Include *.txt).FullName -match $filterPattern

【讨论】:

  • 为什么是非捕获组?简单地加入字符串也应该起作用。不过,我建议转义单个字符串。
  • 当您以编程方式构建正则表达式时,您应该始终转义字符串。 $filterPattern = '(?:{0})' -f (($filterArray |% { [Regex]::Escape($_) }) -join '|')
【解决方案2】:

使用数组作为-match-contains 运算符的第二个操作数不起作用。基本上你可以采取两种方法:

  • 从数组构建一个正则表达式并将其与-match 运算符一起使用:

    $pattern = @($filterArray | ForEach-Object {[regex]::Escape($_)}) -join '|'
    ... | Where-Object { $_.FullName -match $pattern }
    

这是首选方法。

  • 使用嵌套的Where-Object 过滤器和String.Contains() 方法:

    ... | Where-Object {
        $f = $_.FullName
        $filterArray | Where-Object { $f.Contains($_) }
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 2021-06-13
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多