tl;dr
For calling PowerShell commands you indeed need splatting in order to pass the elements of an array as individual, positional arguments; this requires defining the array in an auxiliary variable that can then be passed with sigil @
in lieu of $
to request splatting:
$myArray = -split $myString # See below for limitations, bottom section for fix
MyPowerShellCommand @myArray # Array elements are passed as indiv. arguments.
While this technique also works with external programs, it isn't strictly necessary there, and you can pass an array directly to achieve the same effect:
MyExternalProgram (-split $myString) # Array elements are passed as indiv. args.
Note that (...)
rather than $(...)
is used to pass the expression as an argument. (...)
is usually sufficient and generally preferable, because $(...)
can have side effects - see this answer for details.
Just to bring the post you link to in your question and your answer here together:
First, to be clear: neither answer, due to splitting by spaces only will deal properly with arguments inside the argument-list string that have embedded spaces (and therefore, of necessity use embedded quoting), e.g., $myString = "arg1 `"arg2 with spaces`" arg3"
would not work as expected - see the bottom section for a solution.
Leaving that aside, the difference is:
When calling an external program, as in the linked post, passing an array causes each element to become its own argument.
- That is,
myExternalProgram (-split $MyString)
would work.
- Note that I'm using the unary form of the
-split
operator for more flexible tokenization, which splits by any non-empty run of whitespace while ignoring leading and trailing whitespace (same as awk
's default behavior).
When calling a PowerShell command, as in your case, an array is by default passed as-is, as a whole, as a single argument.
To achieve the same effect as with external programs, i.e. to pass the array's elements as individual, positional arguments, you indeed have to use splatting, i.e. you have to:
- save the array in a variable first:
$myArray = -split $myString
,
- which you can then pass as as a splatted argument by using
@
instead of $
as the sigil: MyPowerShellCommand @myArray
Do note that when calling PowerShell commands it is more common - and more robust - to use hashtable- rather than an array-based splatting, as it allows you to explicitly bind to parameters by name rather than by position - and PowerShell commands often have parameters that can only be bound by name.
- E.g., if
MyPowerShellCommand
accepts parameters -Foo
and -Bar
, you could use:
$myArgs = @{ Foo='foo value'; Bar='bar value '}; MyPowerShellCommand @myArgs
If you do want to handle argument-list strings that have arguments with embedded quoting:
$myString = 'arg1 "arg2 with spaces" arg3'
$myArray = (Invoke-Expression ('Write-Output -- ' + $myString -replace '\$', "`0")) -replace "`0", '$$'
Note: Invoke-Expression
(iex
) should generally be avoided, but the extra precautions taken in this particular command make its use safe.
$myArray
is then a 3-element array with verbatim elements arg1
, arg2 with spaces
and arg3
, which can again be used as shown above.
See this answer for an explanation of the technique.