2012-09-11 16 views
16

Estoy intentando crear una (2.0) script de PowerShell que acepte los argumentos que siguen este patrón básico:Powershell no posicionales, params opcionales

.\{script name} [options] PATH 

Donde las opciones son cualquier número de parámetros opcionales - pensar lo largo las líneas de '-v' para verboso. El argumento PATH simplemente será cualquier argumento pasado por último, y es obligatorio. Uno podría llamar al guión sin opciones y solo un argumento, y ese argumento se supondría que era el Camino. Tengo problemas para configurar una lista de parámetros que solo contenga parámetros opcionales, pero que tampoco sea posicional.

Este script rápida demuestra el problema que estoy teniendo:

#param test script 
Param(
    $firstArg, 
    $secondArg, 
    [switch]$thirdArg, 
    [Parameter(ValueFromRemainingArguments = $true)] 
    $remainingArgs) 

write-host "first arg is $firstArg" 
write-host "second arg is $secondArg" 
write-host "third arg is $thirdArg" 
write-host "remaining: $remainingArgs" 

Cuando se llama así:

.\param-test.ps1 firstValue secondValue 

Las salidas de guión:

first arg is firstValue 
second arg is secondValue 
third arg is False 
remaining: 

El comportamiento Estoy tratando para crear tendría ambos argumentos caer a través de th e params opcionales y terminan en la variable restante de Args.

This question/answer proporcionado amablemente una forma de lograr el comportamiento deseado, pero sólo parece funcionar si hay al menos un parámetro obligatorio, y sólo si se trata antes de todos los otros argumentos.

puedo demostrar este comportamiento al hacer firstArg obligatorios y especificar una posición de 0:

#param test script 
Param(
    [Parameter(Mandatory=$true, Position = 0)] 
    $firstArg, 
    $secondArg, 
    [switch]$thirdArg, 
    [Parameter(ValueFromRemainingArguments = $true)] 
    $remainingArgs) 

    write-host "first arg is $firstArg" 
    write-host "second arg is $secondArg" 
    write-host "third arg is $thirdArg" 
    write-host "remaining: $remainingArgs" 

Run con la misma entrada que antes:

.\param-test.ps1 firstValue secondValue 

La salida es la siguiente:

first arg is firstValue 
second arg is 
third arg is False 
remaining: secondValue 

Se asigna el primer argumento obligatorio, y todo lo que queda cae por completo a través de h.

La pregunta es la siguiente: ¿Cómo puedo configurar una lista de parametros de tal manera que todos los de los parametros son opcionales, y ninguno de ellos es posicional?

Respuesta

23

¿Qué tal esto?

function test 
{ 
    param(
     [string] $One, 

     [string] $Two, 

     [Parameter(Mandatory = $true, Position = 0)] 
     [string] $Three 
    ) 

    "One = [$one] Two = [$two] Three = [$three]" 
} 

OneTwo y son opcionales, y sólo se puede especificar por su nombre. Three es obligatorio, y se puede proporcionar sin un nombre.

Estos trabajos:

test 'foo' 
    One = [] Two = [] Three = [foo] 
test -One 'foo' 'bar' 
    One = [foo] Two = [] Three = [bar] 
test 'foo' -Two 'bar' 
    One = [] Two = [bar] Three = [foo] 

Este fallará:

test 'foo' 'bar' 
test : A positional parameter cannot be found that accepts argument 'bar'. 
At line:1 char:1 
+ test 'foo' 'bar' 
+ ~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : InvalidArgument: (:) [test], ParameterBindingException 
    + FullyQualifiedErrorId : PositionalParameterNotFound,test 

Esto no cumplir que su arg obligatoria se coloca el pasado, o que no está nombrado.Pero permite para el patrón de uso básico que desee.

Tampoco permite más de un valor en $Three. Esto podría ser lo que quieras. Pero, si desea tratar múltiples parámetros no nombrados como parte de $Three, agregue el atributo ValueFromRemainingArguments.

function test 
{ 
    param(
     [string] $One, 

     [string] $Two, 

     [Parameter(Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true)] 
     [string] $Three 
    ) 

    "One = [$one] Two = [$two] Three = [$three]" 
} 

ahora cosas como esta obra:

test -one 'foo' 'bar' 'baz' 
    One = [foo] Two = [] Three = [bar baz] 

O incluso

test 'foo' -one 'bar' 'baz' 
    One = [bar] Two = [] Three = [foo baz] 
+0

Exactamente lo que necesitaba. No se me ocurrió que podía usar una arg obligatoria con Position = 0 como _last_ argument. – Fopedush

+0

gracias latkin, ya había quemado una hora en esto. Tenía otra pregunta (que he respondido con crédito para usted) aquí: http://stackoverflow.com/questions/18861701/how-do-i-force-declared-parameters-to-require-explicit-naming – ekkis