3

Does PowerShell support splatting of positional arguments as opposed to named parameters?

2
  • What's provoking the question? Commented Jul 7, 2018 at 0:58
  • Writing a script and building command parameters. Wanted to avoid the use of Invoke-Command, realized I have some positional parameters that aren't named (not prefixed with a -, anyways). Commented Jul 7, 2018 at 1:08

1 Answer 1

12

PowerShell's argument splatting (see Get-Help about_Splatting) offers two fundamental choices:

  • splatting via a hashtable: works for named arguments only (e.g., -Path C:\Windows
  • splatting via an array-like value: works for positional arguments only (e.g., C:\Windows) - except in non-advanced functions that pass all [unbound] arguments through to another command via @args (i.e., by splatting the automatic $args array variable containing all unbound arguments), in which case named arguments are also supported, owing to magic built into @args only.

Note: This dichotomy applies when passing arguments to PowerShell cmdlets / functions (with declared parameters), whereas external programs perform their own argument parsing, which may or may not interpret the set of arguments passed as named.[1]

That said, you can combine either form with regular, individual argument passing - using any combination of individual positional arguments, individual named arguments, hashtable-splatting, and array-splatting.

In both cases, the source data structure must be:

  • stored in a variable beforehand.

  • referenced with sigil @ instead of $.

Note: A future enhancement, detailed in this RFC, may bring the ability to splat expressions directly, without the need for an intermediate variable, though as of PowerShell Core 7 it is unclear when this will be implemented.


Examples:

# Positional binding via *array*. 
# Note that a function's / script block's parameters are by default positional.
PS> $posArgs = 'one', 'two'; & { param($foo, $bar) "`$foo: $foo"; "`$bar: $bar" } @posArgs
$foo: one
$bar: two


# Named binding via *hashtable*
PS> $namedArgs=@{bar='two';foo='one'}; & { param($foo, $bar) "`$foo: $foo"; "`$bar: $bar" } @namedArgs
$foo: one
$bar: two

# *Combining* hashtable splatting with a regular, positional argument
PS> $namedArgs=@{bar='two'}; & { param($foo, $bar) "`$foo: $foo"; "`$bar: $bar" } @namedArgs one
$foo: one
$bar: two     

[1] Splatting with external programs:

Generally, you do not need splatting when you call external programs, because:

  • You can pass arrays as-is (with the usual $ sigil)

    • The only exception is if you wanted to include %--, the stop-parsing symbol (see Get-Help about_Parsing, in the array of arguments; you do need to use the @ sigil in that event.

    • Use the individual array elements to satisfy the external program's syntax requirements, including its named arguments, if any
      (e.g., $args = '/c', 'ver'; cmd $args to execute cmd /c ver).

  • The way hashtable splats are translated into command-line tokens may or may not be recognized by external programs:

    • Specifically, a hashtable entry with key <paramName> and value <value> is translated into a single argument formatted as -<paramName>:<value> - a format that few external command-line utilities recognize.
Sign up to request clarification or add additional context in comments.

Comments

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.