Search code examples
powershellassignment-operator

Powershell assignment in expression?


Does Powershell have an operator like Python's :=, which can assign a variable within an expression? (e.g., if (match := pattern.search(data)) is not None)
Suppose I want to store a value in Powershell as a variable, but also pass it down the pipeline. Is there a more elegant way than ...| ForEach-Object { $foo = $_.split(': ')[1]; $foo } |...?


Solution

  • I'm trying to pipe an expression, but also store it as a variable for 2 steps down the pipe

    In this case you might consider using the common parameter -PipelineVariable (-pv). It has the advantage that the variable doesn't pollute the parent scope of the pipeline as explicitly assigning to a variable would do. It will just live as long as the pipeline runs.

    ...| ForEach-Object -PipelineVariable foo { $_.split(': ')[1] }
    

    A reproducible example will make the difference clearer:

    1..3 | ForEach-Object { ($a = $_) } | ForEach-Object { $_ * 2 } | ForEach-Object { "$a * 2 = $_" }
    $a  # Print the value of $a
    

    Output:

    1 * 2 = 2
    2 * 2 = 4
    3 * 2 = 6
    3
    

    Note that it ouputs the value of $a in the last line, because the variable has "leaked" from the pipeline into the parent scope. This may be an undesired side effect when you actually wanted to use $a only within the pipeline scope.

    Now see what happens when we change to -PipelineVariable:

    1..3 | ForEach-Object -PipelineVariable a { $_ } | ForEach-Object { $_ * 2 } | ForEach-Object { "$a * 2 = $_" }
    $a  # Print the value of $a
    

    Output:

    1 * 2 = 2
    2 * 2 = 4
    3 * 2 = 6
    

    Now $a after the pipeline doesn't output anything, because the variable is defined only within the pipeline scope.