I have to filter my results by certain strings and tried to do it with -match
and -contains
.
-match
works if i have just one value to filter, but not with an array.
-contains
neither works with one string, nor with a string array-
Why isn't it working with several values? Especially the -contains
.
Or is there another easy way to solve it?
$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 }
Using an array as the second operand for the -match
or -contains
operators doesn't work. There are basically 2 approaches you could take:
Build a regular expression from the array and use that with the -match
operator:
$pattern = @($filterArray | ForEach-Object {[regex]::Escape($_)}) -join '|'
... | Where-Object { $_.FullName -match $pattern }
This is the preferred approach.
Use a nested Where-Object
filter and the String.Contains()
method:
... | Where-Object {
$f = $_.FullName
$filterArray | Where-Object { $f.Contains($_) }
}
Why isn't it working with several values?
Because these operators were designed to test against a single argument, plain and simple.
The ability to match against multiple arguments in a single operation would beg the question: "Does the input need to satisfy ALL or ANY of the argument conditions"?
If you want to test for a match against any of an array of regex patterns, you can construct a single pattern from them using a non-capturing group, like so:
$filterPattern = '(?:{0})' -f ($filterArray -join '|')
Get-ChildItem -Path $Folder -Recurse -Include *.txt | Where {$_.FullName -match $filterPattern} |ForEach-Object{ $_.FullName }
You can also drop the Where-Object
and ForEach-Object
loop completely, since PowerShell 3.0 supports property enumeration:
(Get-ChildItem -Path $Folder -Recurse -Include *.txt).FullName -match $filterPattern