Reputation: 203
Is there a way to combine parameters for multiple logical operators in a where statement?
Basically I have a statement like this:
<command chain> | where {$_.user.tostring() -ne "USER1" -and $_.user.tostring() -ne "USER2" -and $_.user.tostring() -ne "USER3"}
It's actually a fairly long chain, so I'd like to simplify it so that it becomes something like this:
<command chain> | where {$_.user.tostring() -ne {"USER1" -or "USER2" -or "USER3"}}
The above statement doesn't work, so any suggestions please on how to go about this?
Upvotes: 7
Views: 20283
Reputation: 23663
When the input of an operator is a scalar value, the operator returns a Boolean value. When the input is a collection, the operator returns the elements of the collection that match the right-hand value of the expression. If there are no matches in the collection, comparison operators return an empty array. For example:
<command chain> | where {"USER1", "USER2", "USER3" -ne $_.user.tostring()}
Upvotes: 0
Reputation: 11
Assuming your dealing with a array it can be done in this similar fashion you wrote it, even shorter check this out:
PS Z:\> @("food","drink","cheese","dog") -match "(food|cheese)"
food
cheese
PS Z:\> @("food","drink","cheese","dog") -notmatch "(food|cheese)"
drink
dog
where clause:
PS Z:\> @("food","drink","cheese","dog") | where {$_ -notmatch "(food|cheese)"}
drink
dog
Upvotes: 1
Reputation: 32170
You want to use this:
where {$_.user.tostring() -notin ("USER1","USER2","USER3")}
Or this:
where {($_.user.tostring() -ne "USER1") -and ($_.user.tostring() -ne "USER2") -and ($_.user.tostring() -ne "USER3") }
That's really about as simple as you can get. The boolean operators should, in general, only be used to combine comparison operators (or other things you know represent boolean values).
Your code here:
where {$_.user.tostring() -ne {"USER1" -or "USER2" -or "USER3"}}
This is basically nonsense. It's always going to evaluate to true. {"USER1" -or "USER2" -or "USER3"}
is of datatype ScriptBlock.
PS C:\> ({"USER1" -or "USER2" -or "USER3"}).GetType().FullName
System.Management.Automation.ScriptBlock
I believe PowerShell will cast this to a string, but even if it gets cast to a string, it's still not evaluated as a boolean expression:
PS C:> ({"USER1" -or "USER2" -or "USER3"}).ToString()
"USER1" -or "USER2" -or "USER3"
That's going to evaluate to True unless the user is literally '"USER1" -or "USER2" -or "USER3"'
If you changed it so that it was a parenthetic expression instead of a script block:
where {$_.user.tostring() -ne ("USER1" -or "USER2" -or "USER3")}
Then it would always be true. ("USER1" -or "USER2" -or "USER3")
is of type Boolean, and will always have the value of true.
PS C:\> ("USER1" -or "USER2" -or "USER3")
True
So you're basically running:
where {$_.user.tostring() -ne $true }
Again, even if PowerShell converts everything to a string like I think it will, it's pretty unlikely you've got a user named "True". So this will always be true.
Upvotes: 9