Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

syntax - Can you splat positional arguments in PowerShell?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 not too many external command-line utilities recognize.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...