1

I want to do something like that:

param (
    [String[]]${firstArray},
    [string[]]${secondArray}
    )
Write-Host "firstArray: $firstArray"
Write-Host "args: $args"
Write-Host "secondArray: $secondArray"

but I want it to ne called without the "," actually the result is:

.\test.ps1 -firstArray args1 args2 -secondArray args3 args4
firstArray: args1
args: args2 args4
secondArray: args3 

but I want a way to do this:

.\test.ps1 -firstArray args1 args2 -secondArray args3 args4
firstArray: args1 args2
args: 
secondArray: args3 args4

I know that it's possble to to that with a "," like that:

.\test.ps1 -firstArray args1, args2 -secondArray args3, args4
firstArray: args1 args2
args: 
secondArray: args3 args4

but I want to know if it's possible without.

3 Answers 3

2

You can decorate a parameter with ValueFromRemainingArguments:

function f {
  param(
    [Parameter(ValueFromRemainingArguments)]
    [String[]]${firstArray},
    [string[]]${secondArray}
  )

  Write-Host "firstArray: $firstArray"
  Write-Host "args: $args"
  Write-Host "secondArray: $secondArray"
}
PS ~> f -secondArray 1,2,3 a b c d
firstArray: a b c d
args:
secondArray: 1 2 3
Sign up to request clarification or add additional context in comments.

3 Comments

thanks but I want it to be possible on each argument, I'll edit my question.
@NemuraNai I'm afraid that's not possible (making PowerShell's builtin parameter binder do that for you) - your best bet would be to manually inspect $MyInvocation inside the function body and re-assign arguments - not something I'd recommend :-) What's your motivation for trying to evoke this very specific behavior? What problem are you trying to solve?
It's an exercise, it should be called with: f -firstArray arg1 arg2 or with: f -secondArray arg1 arg2 so I realise it be more pertinent to use switch because firstArray and secondArray shouldn't be called together.
2

Mathias' helpful answer shows you how to use the ValueFromRemainingArguments parameter-attribute property to declare a parameter that collects all arguments that:

  • didn't bind to any other parameters,
  • which implies that they can only be positional, i.e. unnamed, meaning: not preceded by the parameter name, such as -firstArray

In other words: If you use ValueFromRemainingArguments to declare $firstArray (-firstArray) there are only two, mutually exclusive ways to pass multiple (an array of) arguments to it:

  • By naming the target parameter, which then requires , to separate the (sub)arguments:

    • .\test.ps1 -firstArray args1, args2 -secondArray args3, args4
  • If you want to be able to separate the arguments with spaces you must not name the target parameter, i.e. you must pass the arguments positionally:

    • .\test.ps1 args1 args2 -secondArray args3, args4

PowerShell doesn't allow you to mix these two approaches; that is, your desired syntax:

.\test.ps1 -firstArray args1 args2 ... does not work.


Working around this, if possible at all, would be a nontrivial amount of work, but more importantly, fighting PowerShell's parameter syntax to superimpose custom logic is conceptually problematic, not least because it will only work with your scripts/functions, not generally.

Comments

1

It is possible when you don't declare any function arguments (i. e. not using the param block). Then the automatic variable $args will contain all argument tokens and you can apply your own interpreting logic.

Function Fun {
    [String[]] $firstArray  = @()
    [String[]] $secondArray = @()
    [ref] $arrayToAppend = $null

    # For each argument token
    foreach( $token in $args ) {
        if( $token -eq '-firstArray' ) {
            # Enter 1st array parsing mode
            $arrayToAppend = [ref] $firstArray
        }
        elseif( $token -eq '-secondArray' ) {
            # Enter 2nd array parsing mode
            $arrayToAppend = [ref] $secondArray
        }
        elseif( $null -ne $arrayToAppend ) {
            # Append to either 1st or 2nd array
            $arrayToAppend.Value += $token
        }
    }

    "firstArray : $($firstArray -join ', ')"
    "secondArray: $($secondArray -join ', ')"
}

Fun -firstArray 1 2 -secondArray 3 4

Output:

firstArray : 1, 2
secondArray: 3, 4

Explanation:

In the function code I'm using a reference variable $arrayToAppend, which will refer to either the 1st or the 2nd array. So by appending to the Value member of this variable, we will actually append to one of both arrays.

Notes:

I agree with mklement0 that this is conceptually problematic. If another developer sees the calling code, it could confuse them, because it differs from regular PowerShell code for passing array literals.

That being said, there might be valid uses for such code, e. g. for backwards compatibility with existing tool chains.

1 Comment

Thanks for updating. Not to put too fine a point on it, but I don't think the don't-do-this-part should be an afterthought, for the sake of future readers. The OP in essence asked: how do I something PowerShell wasn't designed to do? And you gave a good answer to that, but in the grand scheme of things the don't-do-this aspect is more important.

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.