4

How do I elegantly crossbreed Where-Object with ForEach-Object?

The Where-Object cmdlet, has a very elegant way to filter objects: Which use to be the syntax:

... |Where-Object { $_.Id -eq 2 } | ...

Can now be written as:

... |Where-Object Id -eq 2 | ...

I am looking for a similar pipeline conditional statement but instead of filtering the objects in the pipeline, I want to change the concerned objects in the pipeline and pass everything. Like this:

... |ForEach-Object { if ($_.Id -eq 2) { $_.Name = 'test' }; $_ } | ...

In other words, is there a way to write the above syntax with less brackets, parenthesis and current object ($_) references. Like in the self-answer but without using an additional function?

1 Answer 1

3

Using the MetaProgramming module, I was able to write a If-Object cmdlet on top of the Where-Object cmdlet:

function If-Object {
    [CmdletBinding(DefaultParameterSetName='EqualSet', HelpUri='https://go.microsoft.com/fwlink/?LinkID=2096806', RemotingCapability='None')]
    param(
        [Parameter(ValueFromPipeline=$true)]
        [psobject]
        ${InputObject},

        [Parameter(ParameterSetName='ScriptBlockSet', Mandatory=$true, Position=0)]
        [scriptblock]
        ${FilterScript},

        [Parameter(ParameterSetName='Not', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='NotEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveNotEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='GreaterThanSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterThanSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='LessThanSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveLessThanSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='GreaterOrEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterOrEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='LessOrEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveLessOrEqualSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='LikeSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveLikeSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='NotLikeSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveNotLikeSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='MatchSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveMatchSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='NotMatchSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveNotMatchSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='ContainsSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveContainsSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='NotContainsSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveNotContainsSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='InSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveInSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='NotInSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='CaseSensitiveNotInSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='IsSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='IsNotSet', Mandatory=$true, Position=0)]
        [Parameter(ParameterSetName='EqualSet', Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        ${Property},

        [Parameter(ParameterSetName='InSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveEqualSet', Position=1)]
        [Parameter(ParameterSetName='NotEqualSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveNotEqualSet', Position=1)]
        [Parameter(ParameterSetName='GreaterThanSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterThanSet', Position=1)]
        [Parameter(ParameterSetName='LessThanSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveLessThanSet', Position=1)]
        [Parameter(ParameterSetName='GreaterOrEqualSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterOrEqualSet', Position=1)]
        [Parameter(ParameterSetName='LessOrEqualSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveLessOrEqualSet', Position=1)]
        [Parameter(ParameterSetName='LikeSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveLikeSet', Position=1)]
        [Parameter(ParameterSetName='NotLikeSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveNotLikeSet', Position=1)]
        [Parameter(ParameterSetName='MatchSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveMatchSet', Position=1)]
        [Parameter(ParameterSetName='NotMatchSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveNotMatchSet', Position=1)]
        [Parameter(ParameterSetName='ContainsSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveContainsSet', Position=1)]
        [Parameter(ParameterSetName='NotContainsSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveNotContainsSet', Position=1)]
        [Parameter(ParameterSetName='EqualSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveInSet', Position=1)]
        [Parameter(ParameterSetName='NotInSet', Position=1)]
        [Parameter(ParameterSetName='CaseSensitiveNotInSet', Position=1)]
        [Parameter(ParameterSetName='IsSet', Position=1)]
        [Parameter(ParameterSetName='IsNotSet', Position=1)]
        [System.Object]
        ${Value},

        [Parameter(ParameterSetName='EqualSet')]
        [Alias('IEQ')]
        [switch]
        ${EQ},

        [Parameter(ParameterSetName='CaseSensitiveEqualSet', Mandatory=$true)]
        [switch]
        ${CEQ},

        [Parameter(ParameterSetName='NotEqualSet', Mandatory=$true)]
        [Alias('INE')]
        [switch]
        ${NE},

        [Parameter(ParameterSetName='CaseSensitiveNotEqualSet', Mandatory=$true)]
        [switch]
        ${CNE},

        [Parameter(ParameterSetName='GreaterThanSet', Mandatory=$true)]
        [Alias('IGT')]
        [switch]
        ${GT},

        [Parameter(ParameterSetName='CaseSensitiveGreaterThanSet', Mandatory=$true)]
        [switch]
        ${CGT},

        [Parameter(ParameterSetName='LessThanSet', Mandatory=$true)]
        [Alias('ILT')]
        [switch]
        ${LT},

        [Parameter(ParameterSetName='CaseSensitiveLessThanSet', Mandatory=$true)]
        [switch]
        ${CLT},

        [Parameter(ParameterSetName='GreaterOrEqualSet', Mandatory=$true)]
        [Alias('IGE')]
        [switch]
        ${GE},

        [Parameter(ParameterSetName='CaseSensitiveGreaterOrEqualSet', Mandatory=$true)]
        [switch]
        ${CGE},

        [Parameter(ParameterSetName='LessOrEqualSet', Mandatory=$true)]
        [Alias('ILE')]
        [switch]
        ${LE},

        [Parameter(ParameterSetName='CaseSensitiveLessOrEqualSet', Mandatory=$true)]
        [switch]
        ${CLE},

        [Parameter(ParameterSetName='LikeSet', Mandatory=$true)]
        [Alias('ILike')]
        [switch]
        ${Like},

        [Parameter(ParameterSetName='CaseSensitiveLikeSet', Mandatory=$true)]
        [switch]
        ${CLike},

        [Parameter(ParameterSetName='NotLikeSet', Mandatory=$true)]
        [Alias('INotLike')]
        [switch]
        ${NotLike},

        [Parameter(ParameterSetName='CaseSensitiveNotLikeSet', Mandatory=$true)]
        [switch]
        ${CNotLike},

        [Parameter(ParameterSetName='MatchSet', Mandatory=$true)]
        [Alias('IMatch')]
        [switch]
        ${Match},

        [Parameter(ParameterSetName='CaseSensitiveMatchSet', Mandatory=$true)]
        [switch]
        ${CMatch},

        [Parameter(ParameterSetName='NotMatchSet', Mandatory=$true)]
        [Alias('INotMatch')]
        [switch]
        ${NotMatch},

        [Parameter(ParameterSetName='CaseSensitiveNotMatchSet', Mandatory=$true)]
        [switch]
        ${CNotMatch},

        [Parameter(ParameterSetName='ContainsSet', Mandatory=$true)]
        [Alias('IContains')]
        [switch]
        ${Contains},

        [Parameter(ParameterSetName='CaseSensitiveContainsSet', Mandatory=$true)]
        [switch]
        ${CContains},

        [Parameter(ParameterSetName='NotContainsSet', Mandatory=$true)]
        [Alias('INotContains')]
        [switch]
        ${NotContains},

        [Parameter(ParameterSetName='CaseSensitiveNotContainsSet', Mandatory=$true)]
        [switch]
        ${CNotContains},

        [Parameter(ParameterSetName='InSet', Mandatory=$true)]
        [Alias('IIn')]
        [switch]
        ${In},

        [Parameter(ParameterSetName='CaseSensitiveInSet', Mandatory=$true)]
        [switch]
        ${CIn},

        [Parameter(ParameterSetName='NotInSet', Mandatory=$true)]
        [Alias('INotIn')]
        [switch]
        ${NotIn},

        [Parameter(ParameterSetName='CaseSensitiveNotInSet', Mandatory=$true)]
        [switch]
        ${CNotIn},

        [Parameter(ParameterSetName='IsSet', Mandatory=$true)]
        [switch]
        ${Is},

        [Parameter(ParameterSetName='IsNotSet', Mandatory=$true)]
        [switch]
        ${IsNot},

        [Parameter(ParameterSetName='Not', Mandatory=$true)]
        [switch]
        ${Not},

        [Parameter(ParameterSetName='Not', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='NotEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveNotEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='GreaterThanSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterThanSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='LessThanSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveLessThanSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='GreaterOrEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveGreaterOrEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='LessOrEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveLessOrEqualSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='LikeSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveLikeSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='NotLikeSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveNotLikeSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='MatchSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveMatchSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='NotMatchSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveNotMatchSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='ContainsSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveContainsSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='NotContainsSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveNotContainsSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='InSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveInSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='NotInSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='CaseSensitiveNotInSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='IsSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='IsNotSet', Mandatory=$true, Position=2)]
        [Parameter(ParameterSetName='EqualSet', Mandatory=$true, Position=2)]
        [ValidateNotNullOrEmpty()]
        ${Process})

    begin
    {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
            {
                $PSBoundParameters['OutBuffer'] = 1
            }
            [Void]$PSBoundParameters.Remove("Process")
            
            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Core\Where-Object', [System.Management.Automation.CommandTypes]::Cmdlet)
        } catch {
            throw
        }
    }

    process
    {
        try {
            if (& $wrappedCmd @PSBoundParameters) {
                if ($Process -is [ScriptBlock]) { & $Process }
                else { $_.$Property = $Process }
            }
            $_
        } catch {
            throw
        }
    }
}

Example 1

$Test = @(
    [PSCustomObject]@{Id = 1; Name = 'One'}
    [PSCustomObject]@{Id = 2; Name = 'Two'}
    [PSCustomObject]@{Id = 3; Name = 'Three'}
)

$Test |If-Object Id -eq 2 'test' |Format-Table

  Id Name
  -- ----
   1 One
test Two
   3 Three

Example 2

$Test = @(
    [PSCustomObject]@{Id = 1; Name = 'One'}
    [PSCustomObject]@{Id = 2; Name = 'Two'}
    [PSCustomObject]@{Id = 3; Name = 'Three'}
)

$Test |If-Object Id -eq 2 { $_.Name = 'test' } |Format-Table

Id Name
-- ----
 1 One
 2 test
 3 Three
Sign up to request clarification or add additional context in comments.

1 Comment

What happens when you have two conditions, or need a nested ForEach? I personally prefer your "bad" example in the question, just with some line breaks. Or even better, using Foreach ($item in $list) { Do-Thing -to $item } instead of pipelining all your data.

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.