PS_functions_wallchart_1_0_1.jpg
PS_functions_wallchart_1_0_11.jpg
PS_functions_wallchart_1_0_12.jpg
PowerShell Functions: Pipelines, Parameters, and Templates
Download the latest version of this PowerShell
wallchart and see the accompanying in-depth article Down the Rabbit Hole: A Study in
PowerShell Pipelines, Functions, and Parameters
from Simple-Talk at
http://bit.ly/pIl44i
Function Structure
Standard Structure
Special Case
Implicit Format
Sub-blocks (begin, process, and end) support
pipeline processing with pre-
and post-
processing components.
There are two abbreviated formats:
·
All code
in the end
block is equivalent
to the
quintessential, simple function.
·
All code
in the process
block can be
simplified with the filter
keyword.
References
Syntax
Pitfalls
Learning PowerShell, about_Functions, about_Functions_Advanced,about_Parameters,
There are 2 right
ways
to call a function
and several
wrong ways; watch out for those
that fail silently!
about_Functions_Advanced_Parameters, about_Pipelines, PowerShell gotchas, $input gotchas,
Parentheses in PowerShell.
Calling Syntax
$a
$b
$c
f(1,2,3)
1,2,3
f(1,2,3)
[StrictMode]
Syntax error–called like a method
Templates
Copyright © 2011
f
(1,2,3)
1,2,3
When you send data into a function, what arrives depends on your
Michael Sorens
f
1,2,3
1,2,3
structure and your invocation. For each template, the table below shows
2011.07.13
f
(1 2 3)
Syntax error–unexpected token
Version 1.0.1
what arrives for all input combinations. The results are color-coded to
f
1 2 3
1
2
3
green (pass) and red (fail) against these expectations: (a) “no input” should
f
–c 3
–a 1
–b 2
1
2
3
yield a default; and (b) a direct or pipeline input should reflexively yield
Direct Input Commands
Pipeline Input Commands
back the input.
TestFunction
@() | TestFunction
TestFunction$null
$null | TestFunction
Group C obviously is the best choice—but only
if you need to satisfy all
those
TestFunction ""
"" | TestFunction
expectations. Group A templates may suffice if you need to handle either direct
TestFunction "one"
"one" | TestFunction
TestFunction "one","two"
"one","two" | TestFunction
input or pipeline input but not both. Group B templates may suffice if you also are
TestFunction "one",$null,"two",""
"one",$null,"two","" | TestFunction
concerned with a default value.
Results of executing input class (right)
No Input
Null
Empty
Scalar
List
List with Null/Empty
String
against template
(below)
($null)
("")
(one)
(one,
two)
(one,
$null,
two,
"")
function Template-A_1_Basic($item)
$null
$null
""
one
one,two
one, $null,two,""
{
$item | % { return $_ }
$null
$null
$null
$null
$null
$null
}
function Template-A_2_Process($item)
$null
$null
$null
$null
$null
$null
{
Process
{ return $_
}
$null
$null
""
one
one,two
one, $null,two,""
}
function Template-A_3_Input($item)
$null
$null
$null
$null
$null
$null
{
$input
| % { return $_ }
$null
$null
""
one
one,two
one, $null,two,""
}
function Template-B_1_BasicDefault(
default
$null
""
one
one,two
one, $null,two,""
[array]$item = "default")
{
default
default
default
default
default
default
$item | % { return $_ }
}
function Template-B_2_ProcessDefault(
$null
$null
$null
$null
$null
$null
[array]$item = "default")
{
$null
$null
""
one
one,two
one, $null,two,""
Process
{ return $_
}
}
function Template-B_3_InputDefault(
$null
$null
$null
$null
$null
$null
[array]$item = "default")
{
$null
$null
""
one
one,two
one, $null,two,""
$input
| % { return $_ }
}
function Template-C_1_ProcessDefault_A(
default
$null
""
one
one,two
one, $null,two,""
[array]$item = "default")
{
$null
default
default
one
one,two
one,one,two,two
Process
{
Without properly indicating pipeline input (via ValueFromPipeline), you can add a
if ($_) { $item = $_
}
$item | % { return $_ }
kludge as shown to force pipeline input into $item. The kludge, however, fails to
}
distinguish different types of input that evaluate to false, leading to the curious
}
result for the last test!
function Template-C_2_ProcessDefault_B(
default
$null
""
one
one,two
one, $null,two,""
[Parameter(ValueFromPipeline=$True)]
[array]$item = "default")
$null
$null
""
one
one,two
one,$null,two,""
{
You can simplify this template by converting the function keyword to filter and then
Process
{
$item | % { return $_ }
remove the explicit process block.
Depending on what you deem correct for the
}
standout test case, this template wins in elegance of coding compared to C_3/C_4.
}
function Template-C_3_InputDefault_A(
default
$null
""
one
one,two
one,null,two,""
[Parameter(ValueFromPipeline=$True)]
default
$null
""
one
one,two
one,null,two,""
[array]$item = "default")
{
C_3 and C_4 yield identical results, though C_3 is technically more correct by
$list = @($input)
if ($list.count) { $item = $list }
indicating pipeline input (via ValueFromPipeline). However, that requires adding
if (!(test-path variable:\item))
more code to prevent a runtime error on one test case. Strange but true: the
{ $item = "default" }
function's own $item parameter is undefined if an empty pipeline feeds the
$item | % { return $_ }
function!
}
function Template-C_4_InputDefault_B(
default
$null
""
one
one,two
one,null,two,""
[array]$item = "default")
default
$null
""
one
one,two
one,null,two,""
{
$list = @($input)
Both C_3 and C_4 have elegance in results—the outputs from direct input exactly
if ($list.count) { $item = $list }
$item | % { return $_ }
mirror those from pipeline input.
}