Reputation: 3107
Is it possible to convert following where PS script block
$env:Path -split ";" | where {$_ -like "c:\Program*"}
to a where comparison statement looking like
$env:Path -split ";" | where ???WHAT HERE??? -like "c:\Program*"
What I need is something that would replace the implicit $_ variable from the first statment.
Edit: My intention is pure curiosity. I prefer to use the second way of the where-object cmdlet, however, I do not know how to address the pipe value directly on the left side of the -like operator
Edit2: What is a comparison statement? A comparison statement is much more like natural language. Comparison statements were introduced in Windows PowerShell 3.0. An example:
Get-Process | Where-Object PriorityClass -eq "Normal"
Source: Where-Object on MSDN
Upvotes: 4
Views: 621
Reputation: 32200
Is it possible to convert following where PS script block
$env:Path -split ";" | where {$_ -like "c:\Program*"}
to a where comparison statement looking like
$env:Path -split ";" | where ???WHAT HERE??? -like "c:\Program*"
No, that is not possible.
There are two modes for Where-Object
. Fully expressed, one looks like this:
ls | Where-Object -FilterScript { $_.Name -eq 'File.txt' }
Here, we're writing a scriptblock that contains an expression that is evaluated on every item.
The other mode, fully expressed, actually looks like this.
ls | Where-Object -Property Name -Value File.txt -Eq
Note that the -Eq
here is a parameter and not an operator. We're calling a command, not writing an expression in a scriptblock here. And I know what you're thinking. "But to work that way, the command would need to have a different parameter set for every conceivable operator!" And that's exactly what they do!
Where-Object [-InputObject <PSObject>] [-Property] <String> [[-Value] <Object>] [-EQ] [<CommonParameters>]
Where-Object [-InputObject <PSObject>] [-Property] <String> [[-Value] <Object>] [-NE] [<CommonParameters>]
Where-Object [-InputObject <PSObject>] [-Property] <String> [[-Value] <Object>] [-LT] [<CommonParameters>]
[...]
The -InputObject
parameter is the value from the pipeline. -Property
is the first positional parameter. -Value
is the second positional parameter.
The problem is that the -Property
parameter is mandatory. You can't call this command without specifying a parameter name and there's no property name that means "this object".
Upvotes: 3
Reputation: 1782
You could write your own pipe function like this:
Add-Type -AssemblyName System.Collections
function where-special {
[cmdletbinding()]
param(
[Parameter(ValueFromPipeline=$true)]
[object[]]$piped,
[Parameter(Position=1, ParameterSetName="eq")]
[object]$eq,
[Parameter(Position=1, ParameterSetName="like")]
[object]$like,
[Parameter(Position=1, ParameterSetName="match")]
[object]$match )
Begin {
[System.Collections.Generic.List[object]]$found = @()
$toDo = [Scriptblock]::Create( 'if( $piped -' + $PSCmdlet.ParameterSetName + ' $' + $PSCmdlet.ParameterSetName + ') { $found.Add( $piped ) }' )
}
Process {
& $toDo
}
End {
return $found.ToArray()
}
}
$env:Path -split ";" | where-special -like 'C:\Windows'
Upvotes: 1
Reputation: 2318
$env:Path -split ";" | where { $_.StartsWith("C:\Program") -eq $True }
Upvotes: -1