2

Okay, I'm still fairly new to PowerShell.

I've written a piece of code that works, but it smells entirely wrong. What is the right way to write this from a PowerShell standpoint?

$filters = @("*a*","*b*")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

Write-Host "Filters" -ForegroundColor Yellow
$filters 
Write-Host "Data" -ForegroundColor Yellow
$data

$results = @()

foreach ($d in $data)
{
    [bool] $skip = $false
    foreach ($filter in $filters)
    {
        if ($d -like $filter)
        {
            $skip = $true
        }
    }

    if ($skip -eq $false)
    {
        $results += $d
    }
}

Write-Host "Desired Results" -ForegroundColor Yellow
$desiredResults
Write-Host "Results" -ForegroundColor Yellow
$results

5 Answers 5

6

you can do like this

$filters = @("a","b")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

$data | Select-String -Pattern $filters -NotMatch
Sign up to request clarification or add additional context in comments.

2 Comments

i like this solution, gj!
Exactly what I needed for this issue. Clean and easy to read.
2

The right way? I don't know that there is a right way. I can give you what I consider a better way using RegEx:

$filters = @("a","b")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

$RegExFilter = ($Filters|%{[regex]::escape($_)}) -join '|'

$Results = $data | Where{$_ -notmatch $RegExFilter}

Write-Host "Desired Results" -ForegroundColor Yellow
$desiredResults
Write-Host "Results" -ForegroundColor Yellow
$results

This basically takes each element of the $filters array, performs a regex escape on it to escape any special characters, and then joins all of those results with a pipe character. So in the example given $RegExFilter equals a|b. Then it filters $data against anything that matches that pattern.

1 Comment

I like this one as well. The reusable aspect is awesome. I have to go with the Select-String option though just because it is easier to read at a glance. Definitely going to save this snippet as well.
1

I frequently have problems with double pipelines so I switch one to ForEach.
Here is a one-liner.

$filters = @("*a*","*b*")
$data = @("c/a","c/b","c/a/d","e","a","e/f")

ForEach ($Item in $data) { If ( !($filters | Where-Object {$Item -like $_})) { $Item } }

Comments

0

The only real problem here - is you have to compare string to and array of strings, which I don't think powershell can do elegantly (but I might be wrong), so I've done this:

foreach ($d in $data)
{
    if ($d -notlike $filters[0] -and $d -notlike $filters[1])
    {
        $results += $d
    }
}

I assume the syntaxis is clean enough and doesn't need any explanation. if it needs explanation, tell me in comments.

Comments

0

try this

$data | %{$val=$_; $Nb=($filters | where {$val -like $_}).Count ; if ($Nb -eq 0) {$val} }

2 Comments

This one doesn't match my expected results. It only filters out one value ("a").
Strange it work on my pc. What is your PowerShell version?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.