cómo paso un rango de valores en la línea de comando, pasando una expresión como argumento

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 de 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 sólido al declarar su parámetro con un tipo más específico , en cuyo caso un bash de invocarlo con una cadena fallaría de inmediato:

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

(Otras optimizaciones podrían aplicarse también a su secuencia de comandos).


Información de fondo opcional

En cuanto a cuando un argumento no cotejado se trata como una expresión frente a una cadena ( ampliable) (en modo de argumento ):

  • (...) , $(...) y @(...) crean un nuevo contexto de análisis , en el que se pueden usar expresiones o incluso comandos nesteds :

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

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

      • [...] (referencias de tipo) como [Environment]::Version
      • .. (expresiones de rango) como 1..10
  • A @ seguido del nombre de una variable (p. Ej., @params ) que contiene una colección o hashtable de valores de parámetros inicia el splatting de parámetros .

  • @{ ... } puede usarse para pasar un literal hashtable (p. ej., @{ key = 'value' } ).

  • Por sí mismos , las referencias de variables, incluido el acceso de índice / propiedad e incluso las llamadas a métodos, se pueden usar tal como están :

    • Por sí mismos , se reconocen los tokens como $HOME , $PSVersionTable.PSVersion y $someArray[0] , y se devuelven como su tipo inherente. Incluso puede llamar a un método de esta manera (por ejemplo, $PSVersionTable.ContainsKey('PSVersion') ).

    • Las reglas cambian si directamente anexa o anexa caracteres a la referencia de variable o a la llamada a un método, consulte a continuación.

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

    • Ampliable significa que las referencias de variables simples incorporadas (por ejemplo, $HOME\Desktop o $env:APPDATA\Test ) se interpolan (reemplazan con sus valores codificados).
      Tenga en cuenta que esto puede dar lugar a una representación que difiere del formato de salida predeterminado de un valor determinado, como se muestra en la consola, por ejemplo (de nuevo, consulte esta respuesta para obtener más información).

      • Adjunte un nombre de variable en {...} para eliminar la ambigüedad de los caracteres siguientes, 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 expresiones / expresiones de variables incrustadas en "..." , ya que evita los siguientes casos extremos:

      • $(...) al comienzo de un token no incluido en la lista no se interpreta como parte de una cadena expansible , 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 una subexpresión, da como resultado 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 es uno: el tipo final está determinado por el tipo de parámetro del comando en cuestión al que está vinculado el valor expandido.

    • Escapar / cotizar:

      • PowerShell tiene muchos metacaracteres más que cmd.exe , y un inconveniente notable es que debe escaparse para tratarse literalmente, porque es el operador de construcción de matriz de PowerShell.

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

      • Para evitar la necesidad de escanear 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 insertar referencias de variables y subexpresiones.

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

          • Dentro de una cadena de una sola cita, escapa un ' como ''
      • Las comillas sencillas o dobles son generalmente la forma más fácil de escapar espacios en un valor.

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


[1] Los metacaracteres en modo argumento (caracteres con un significado sintáctico especial) son:
' " ` , ; ( ) { } | & < > @ # .
De estos, < > @ # son solo 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 (eg) 'C:\Users\jdoe\Desktop' Write-Output "$HOME\Desktop" # ditto Write-Output '$HOME\Desktop' # LITERAL string '$HOME\Desktop' Write-Output dir=$HOME # EXPANDED string (eg) 'dir=C:\Users\jdoe\Desktop' Write-Output $PSVersionTable.PSVersion # a [System.Version] instance Write-Output "$($PSVersionTable.PSVersion)/more" # a [string]; eg, '5.1.14393.576/more' Write-Output "v$($PSVersionTable.PSVersion)" # ditto; eg, '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 
    Intereting Posts