Problem
You have a section of your script that works nearly the same for all input, aside from a minor change in logic.
Solution
As shown in Example 103, place the minor logic differences in a script block, and then pass that script block as a parameter to the code that requires it. Use the invoke operator (&) to execute the script block.
Example 103. A script that applies a script block to each element in the pipeline
############################################################################## ## MapObject.ps1 ## ## Apply the given mapping command to each element of the input ## ## Example: ## 1,2,3 | MapObject { $_ * 2 } ############################################################################## param([ScriptBlock] $mapCommand)
process { & $mapCommand }
Discussion
Imagine a script that needs to multiply all the elements in a list by two:
function MultiplyInputByTwo
{ process {
$_ * 2 } }
but it also needs to perform a more complex calculation:
function MultiplyInputComplex
{ process {
($_ + 2) * 3 } }
These two functions are strikingly similar, except for the single line that actually performs the calculation. As we add more calculations, this quickly becomes more evident. Adding each new seven line function gives us only one unique line of value!
PS >1,2,3 | MultiplyInputByTwo 2 4 6 PS >1,2,3 | MultiplyInputComplex
9 12 15
If we instead use a script block to hold this “unknown” calculation, we don’t need to keep on adding new functions:
PS >1,2,3 | MapObject { $_ * 2 } 2 4 6 PS >1,2,3 | MapObject { ($_ + 2) * 3 } 9 12 15 PS >1,2,3 | MapObject { ($_ + 3) * $_ } 4 10 18
In fact, the functionality provided by MapObject is so helpful that it is a standard PowerShell cmdlet—called ForeachObject.