0

I'm attempting to search a hash table for keys that have values that are -notlike or -notmatch 'Snagit'. I am able find an exact match with -notcontains.

Data Example:

Name    Value
Host1   FireFox,Snagit 7,Chrome
Host2   Internet,Chrome
Host3   Snagit 5,Internet,Stuff

Code Example:

$global:Csv = Import-Csv -LiteralPath $global:ConvertedSNWReport

$global:hash = @{}
Import-Csv -LiteralPath $global:ConvertedSNWReport | ForEach-Object {
    $global:hash[$_.'Computer name'] += @($_.Application)
}

$global:Results = $hash.GetEnumerator() | Where-Object {
    $_.Value -notmatch '*Snagit*' 
}
3
  • So, in the example you'd want to grab only the Host2 entry, is that correctly understood? Commented Aug 30, 2017 at 20:43
  • Yes, that is correct. Commented Aug 30, 2017 at 20:46
  • 2
    Note that *Snagit* is not a valid regular expression (-match, -notmatch). It's a pattern for wildcard matches (-like, -notlike). For a regular expression you don't need to match leading or trailing text, since they aren't anchored by default (you need ^ and/or $ for anchoring them), whereas wildcard patterns are by default anchored at beginning and end of a string. Commented Aug 30, 2017 at 21:10

1 Answer 1

3

You can nest your Where-Object statements to accomplish this:

$results = $hash.GetEnumerator() |Where-Object {
    -not($_.Value |Where-Object {$_ -like '*snagit*'})
}

If any of the items in the individual value array matches snagit, the expression will evaluate to $false and the hashtable entrt will be skipped. Conversely, if no items match snagit, it will evaluate to $true


As Ansgar just reminded me, the nested Where-Object statement isn't actually necessary when evaluating strings, since -like doubles as a filter operator on collections:

$results = $hash.GetEnumerator() |Where-Object {
    -not($_.Value -like '*snagit*')
}
Sign up to request clarification or add additional context in comments.

5 Comments

Darn, beat me to it. You don't need the nested Where-Object, though, -not ($_.Value -like '*snagit*') should be sufficient.
To add some explanation, you cannot use -notlike or -notmatch here, because that would filter only matching elements from the values. Unless all array elements match the pattern you'll still end up with a non-empty array, which evaluates to $true. Instead you need to check if any element of the array matches, and then negate that condition to get "no element matches".
@AnsgarWiechers thanks, completely forgot that we're working on bare strings here, I need some sleep ^_^
While both of these options worked, for some reason it looks like I received slightly different results. I end up sorting and then exporting to csv and they're different sizes. e.g. The nested where has more results
It turns out there were incorrect results within the nest where clause.

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.