receive pass parameter example powershell parsing command-line syntax parameter-passing

powershell - pass - ¿Cómo paso un rango de valores en la línea de comando? pasando una expresión como argumento



powershell pass parameters to ps1 file (1)

Tengo el siguiente código:

$srv_range = 29..30+40+50..52 $srv_range.GetType() $NewVMTemplate = New-Object psobject $NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null $srv_range | % { $pod= $_ $servers = @() 1..2 | % { $server = $NewVMTemplate | Select-Object * $server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_ $servers += $server } ForEach ( $server in $servers) { write-host $server.Name } }

salida:

PowerCLI C:/ ./eraseme.ps1 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array pod29-srv1 pod29-srv2 pod30-srv1 pod30-srv2 pod40-srv1 pod40-srv2 pod50-srv1 pod50-srv2 pod51-srv1 pod51-srv2 pod52-srv1 pod52-srv2

Quiero ingresar el rango desde CLI, pero obtengo el siguiente resultado con este código

param( [Parameter(Mandatory=$False)] $srv_range ) #$srv_range = 29..30+40+50..52 $srv_range.GetType() $NewVMTemplate = New-Object psobject $NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null $srv_range | % { $pod= $_ $servers = @() 1..2 | % { $server = $NewVMTemplate | Select-Object * $server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_ $servers += $server } ForEach ( $server in $servers) { write-host $server.Name } } PowerCLI C:/ ./eraseme.ps1 29..30+40+50..52 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object pod29..30+40+50..52-srv1 pod29..30+40+50..52-srv2

¿Cómo puedo ingresar el rango desde CLI y obtener el mismo resultado que el primer código?


Su problema es que el argumento 29..30+40+50..52 se trata como un literal de cadena en su ./eraseme.ps1 29..30+40+50..52 : no se reconoce como una expresión .

Para forzar el reconocimiento como una expresión , simplemente encierre el argumento en (...) :

./eraseme.ps1 (29..30+40+50..52)

Tenga en cuenta que puede hacer que su script sea más robusto declarando su parámetro con un tipo más específico , en cuyo caso un intento de llamarlo con una cadena fallaría de inmediato:

[Parameter(Mandatory=$False)] [int[]] $srv_range

(También se podrían aplicar otras optimizaciones a su secuencia de comandos).

Información de antecedentes opcional

En cuanto a cuando un token sin comillas se trata como una expresión frente a una cadena (expandible) en modo argumento (ver about_Parsing ):

  • (...) , $(...) y @(...) por sí mismos o al comienzo de un token crean un nuevo contexto de análisis , en el que se pueden usar expresiones o incluso comandos anidados :

    • (...) es suficiente para una sola expresión o comando. $(...) (el operador de subexpresión ) puede encerrar múltiples expresiones / comandos; también puede @() (el operador de subexpresión de matriz ), y además garantiza que su salida siempre se trate como una matriz .

    • En particular, las siguientes expresiones no se reconocen sin estar encerradas en una de las anteriores:

      • [...] (escriba literales) y acceso a sus miembros, como [Environment]::Version
      • .. (expresiones de rango) como 1..10
    • Si, al comienzo de un token , (...) , $(...) o @(...) son seguidos por caracteres adicionales, el primer carácter adicional se considera el comienzo de un nuevo argumento separado .

    • Por el contrario, si están precedidos por un literal sin comillas o una referencia de solo variable , $(...) funciona como dentro de "..." (una cadena expandible), (...) comienza un nuevo argumento que es una expresión, y @(...) se toma como literal @ con (...) nuevamente comenzando un nuevo argumento que es una expresión.
  • Una @ seguida del nombre de una variable (p. Ej., @params ) que contiene una colección o una tabla hash de valores de parámetros inicia el splatting de parámetros .

  • @{ ... } se puede usar para pasar un literal de tabla hash (por ejemplo, @{ key = ''value'' } ).

  • { ... } crea un bloque de script ( [scriptblock] ).

  • Por sí mismos o al comienzo de un token , las referencias variables, incluido el acceso a los miembros (acceso a la propiedad, llamadas a métodos, indexación) se pueden usar como están :

    • Expresiones como $HOME , $PSVersionTable.PSVersion , $someArray[0] y $someString.ToUpper() se reconocen y devuelven como su tipo inherente.

    • Sin acceso de miembro, es decir, con una referencia de variable simple como $HOME , los caracteres subsiguientes se consideran (potencialmente) parte del mismo argumento que luego se interpreta como una cadena expandible ; consulte a continuación.

    • Con acceso de miembro, el primero de los caracteres adicionales se considera el inicio de un nuevo argumento (por ejemplo, $foo.Length-more da como resultado dos argumentos: el valor de $foo.Length y string literal $foo.Length ).

  • Todo lo demás se trata como una cadena expandible , es decir, similar al contenido de una cadena entre comillas dobles, excepto que los metacaracteres [1] aún necesitan escapar y ciertos tokens se interpretan como argumentos múltiples .

    • Expandible significa que las referencias de variables simples incrustadas (por ejemplo, $HOME/Desktop o $env:APPDATA/Test ) se interpolan (se reemplazan con sus valores en cadena).
      Tenga en cuenta que esto puede dar como resultado una representación que difiere del formato de salida predeterminado de un valor dado como se muestra en la consola, por ejemplo (nuevamente, consulte esta respuesta para obtener más información).

      • Incluya un nombre de variable en {...} para eliminar la ambigüedad de los caracteres posteriores, si es necesario (por ejemplo, ${HOME} ).
    • Para acceder a la propiedad de un valor variable o usar un índice o llamar a un método o incorporar comandos arbitrarios , debe encerrar la expresión en $(...) , por ejemplo, v$($PSVersionTable.PSVersion)

    • En general, es más seguro encerrar tokens con referencias / expresiones de variables incrustadas en "..." , ya que evita los siguientes casos límite:

      • $(...) al comienzo de un token sin comillas no se interpreta como parte de una cadena expandible , se trata como un argumento separado (por ejemplo, Write-Output $(''ab'')c da como resultado dos argumentos: el resultado de $(''ab'') y literal c ).
      • . al comienzo de un token seguido inmediatamente por una referencia de variable simple o subexpresión resulta en argumentos separados también .
        (Por ejemplo,. .$HOME da como resultado dos argumentos: literal . Y el valor de $HOME )
    • Nota: Aunque el resultado de la expansión es una cadena, no necesariamente sigue siendo una: el tipo final está determinado por el tipo del parámetro del comando en cuestión al que está vinculado el valor expandido.

    • Escapando / citando:

      • PowerShell tiene muchos más metacaracteres que cmd.exe , y un obstáculo notable es que debe ser escapado para ser tratado literalmente, porque es el operador de construcción de matrices de PowerShell.

      • Para escapar de un solo carácter , prefijelo con ` (retroceso) .

      • Para evitar la necesidad de escapar metacaracteres individualmente , encierre el valor en "..." (comillas dobles) o ''...'' (comillas simples) :

        • Use comillas dobles si desea que la cadena se interpole (expanda) , es decir, si desea poder incrustar referencias variables y subexpresiones.

          • Dentro de una cadena entre comillas dobles, ` -escape los siguientes caracteres. tratarlos como literales: ` " $
        • Use comillas simples para tratar el valor como un literal .

          • Dentro de una cadena entre comillas simples, escapa un '' como ''''
      • Las comillas simples o dobles suelen ser la forma más fácil de escapar de espacios en un valor.

  • Finalmente, tenga en cuenta que --% , el llamado símbolo de detener el análisis (PSv3 +), cambia por completo la interpretación de todos los argumentos restantes: diseñado para usar con líneas de comando cmd.exe heredadas, deja de interpretar el resto de la línea excepto expansión de cmd.exe -style %...% variables de entorno . Consulte Get-Help about_Parsing

En cuanto al uso de tokens citados :

  • ''...'' o "..." solos o al comienzo de un token :

    • Estos se analizan como de costumbre: como una cadena literal ( ''...'' ) o expandible ( "..." ).
    • Cualquier carácter adicional hace que el primer carácter adicional se considere el comienzo de un nuevo argumento separado .
  • ''...'' o "..." están precedidos por una referencia literal o entre variables sin comillas :

    • Se evalúan como de costumbre y el resultado (es decir, con las comillas eliminadas) se agrega a lo que les precede (evaluado).

[1] Los metacaracteres en modo argumento (caracteres con significado sintáctico especial) son:
<space> '' " ` , ; ( ) { } | & < > @ # .
De estos, < > @ # solo son especiales al comienzo de un token.

Ejemplos

Write-Output 1..10 # STRING: -> ''1..10'' Write-Output (1..10) # EXPRESSION: -> @(1, 2, ...) # Write-Output $(1..10) would work too, but is only necessary if # the enclosed expression comprises *multiple* statements. Write-Output [Environment]::Version # STRING: -> ''[Environment]::Ticks'' Write-Output ([Environment]::Version) # EXPRESSION: -> a [System.Version] instance. Write-Output a,b # !! ARRAY @(1, 2), because "," is not escaped. Write-Output a`,b #`# STRING ''ab'' Write-Output "a,b" # ditto Write-Output ''a,b'' # ditto Write-Output $HOME/Desktop # EXPANDED string (e.g.) ''C:/Users/jdoe/Desktop'' Write-Output "$HOME/Desktop" # ditto Write-Output ''$HOME/Desktop'' # LITERAL string ''$HOME/Desktop'' Write-Output dir=$HOME # EXPANDED string (e.g.) ''dir=C:/Users/jdoe/Desktop'' Write-Output $PSVersionTable.PSVersion # a [System.Version] instance Write-Output "$($PSVersionTable.PSVersion)/more" # a [string]; e.g., ''5.1.14393.576/more'' Write-Output "v$($PSVersionTable.PSVersion)" # ditto; e.g., ''v5.1.14393.576'' # !!! These DO NOT WORK as intended. Write-Output $($PSVersionTable.PSVersion)/more # $(...) at the *start* Write-Output $PSVersionTable.PSVersion/more # $(...) missing Write-Output "$PSVersionTable.PSVersion/more" # $(...) missing Write-Output .$HOME # Specifically, .$ at the beginning is the problem; escaping . works