I have two PowerShell functions, the first of which invokes the second. They both take N arguments, and one of them is defined to simply add a flag and invoke the other. Here are example definitions:
function inner
{
foreach( $arg in $args )
{
# do some stuff
}
}
function outer
{
inner --flag $args
}
Usage would look something like this:
inner foo bar baz
or this
outer wibble wobble wubble
The goal is for the latter example to be equivalent to
inner --flag wibble wobble wubble
The Problem: As defined here, the latter actually results in two arguments being passed to inner: the first is "--flag", and the second is an array containing "wibble", "wobble", and "wubble". What I want is for inner to receive four arguments: the flag and the three original arguments.
So what I'm wondering is how to convince powershell to expand the $args array before passing it to inner, passing it as N elements rather than a single array. I believe you can do this in Ruby with the splatting operator (the * character), and I'm pretty sure PowerShell can do it, but I don't recall how.
-
Well, there may be a better way, but see if this works:
inner --flag [string]::Join(" ", $args)Charlie : It looks like this doesn't work directly, because the result of string::Join is passed as a single argument, in this case "wibble wobble wubble".EBGreen : hmmm...let me poke around some more -
Building on @EBGreen's idea, and a related question I noticed in the sidebar, a possible solution is this:
function outer { invoke-expression "inner --flag $($args -join ' ')" }Note: This example makes use of the Powershell 2.0 CTP's new
-joinoperator.However, I'd still like to find a better method, since this feels like a hack and is horrible security-wise.
EBGreen : I'm not a fan of invoke expression either, but if you control of the args it isn't terrible. I think CTP2 or CTP3 exposes the tokenizer too in which case you could sanitize the args before the invoke.JasonMArcher : You can do this with PowerShell v1.0 only stuff as well: invoke-expression "inner --flag $args" The array will be joined with spaces by default (there is also a way to change the default character, but I can't remember it).Charlie : Yup, you're correct about that. The separator is controlled by the $OFS variable. -
There isn't a good solution to this problem in PowerSHell V1. In V2 we added splatting (though for various reasons, we use @ instead of * for this purpose). Here's what it looks like:
PS (STA-ISS) (2) > function foo ($x,$y,$z) { "x:$x y:$y z:$z" }
PS (STA-ISS) (3) > $a = 1,2,3
PS (STA-ISS) (4) > foo $a # passed as single arg
x:1 2 3 y: z:
PS (STA-ISS) (5) > foo @a # splatted
x:1 y:2 z:3
Charlie : What an honor to get an answer from one of the PowerShell gurus! I have PowerShell 2 CTP2 installed, so I'll give that a try.Charlie : Looks like that's exactly what I needed, thanks again.
0 comments:
Post a Comment