script - powershell tutorial
¿Cómo paso varios parámetros a una función en PowerShell? (14)
Algunas buenas respuestas aquí, pero quería señalar un par de cosas más. Los parámetros de la función son en realidad un lugar donde PowerShell brilla. Por ejemplo, puede tener parámetros nombrados o posicionales en funciones avanzadas como:
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string] $Name,
[Parameter(Mandatory=$true, Position=1)]
[int] $Id
)
}
Luego puede llamarlo especificando el nombre del parámetro, o simplemente puede usar parámetros posicionales, ya que los definió explícitamente. Así que cualquiera de estos funcionaría:
Get-Something -Id 34 -Name "Blah"
Get-Something "Blah" 34
El primer ejemplo funciona a pesar de que Segundo se proporciona el Nombre, porque usamos explícitamente el nombre del parámetro. Sin embargo, el segundo ejemplo funciona en función de la posición, por lo que Nombre tendría que ser el primero. Cuando es posible, siempre trato de definir posiciones para que ambas opciones estén disponibles.
PowerShell también tiene la capacidad de definir conjuntos de parámetros. Utiliza esto en lugar de la sobrecarga de métodos, y nuevamente es bastante útil:
function Get-Something
{
[CmdletBinding(DefaultParameterSetName=''Name'')]
Param
(
[Parameter(Mandatory=$true, Position=0, ParameterSetName=''Name'')]
[string] $Name,
[Parameter(Mandatory=$true, Position=0, ParameterSetName=''Id'')]
[int] $Id
)
}
Ahora la función tomará un nombre o una identificación, pero no ambos. Puede utilizarlos de forma posicional, o por nombre. Ya que son un tipo diferente, PowerShell lo resolverá. Así que todo esto funcionaría
Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23
También puede asignar parámetros adicionales a los diversos conjuntos de parámetros. (Ese fue un ejemplo bastante básico, obviamente) Dentro de la función, puede determinar qué conjunto de parámetros se usó con la propiedad $ PsCmdlet.ParameterSetName. Por ejemplo:
if($PsCmdlet.ParameterSetName -eq "Name")
{
Write-Host "Doing something with name here"
}
Luego, en una nota lateral relacionada, también hay una validación de parámetros en PowerShell. Esta es una de mis características favoritas de PowerShell, y hace que el código dentro de sus funciones sea muy limpio. Hay numerosas validaciones que puede utilizar. Un par de ejemplos son
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidatePattern(''^Some.*'')]
[string] $Name,
[Parameter(Mandatory=$true, Position=1)]
[ValidateRange(10,100)]
[int] $Id
)
}
En el primer ejemplo, ValidatePattern acepta una expresión regular que garantiza que el parámetro proporcionado coincida con lo que está esperando. Si no es así, se lanza una excepción intuitiva que le dice exactamente qué es lo que está mal. Entonces, en ese ejemplo, ''Algo'' funcionaría bien, pero ''Verano'' no pasaría la validación.
ValidateRange garantiza que el valor del parámetro se encuentre entre el rango que espera para un entero. Así que 10 o 99 funcionarían, pero 101 lanzaría una excepción.
Otro útil es ValidateSet, que le permite definir explícitamente una matriz de valores aceptables. Si se ingresa algo más, se lanzará una excepción. Hay otros también, pero probablemente el más útil es ValidateScript. Esto toma un bloque de script que debe evaluarse a $ true, por lo que el cielo es el límite. Por ejemplo:
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidateScript({ Test-Path $_ -PathType ''Leaf'' })]
[ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
[string] $Path
)
}
En este ejemplo, estamos seguros de que no solo $ Path existe, sino que es un archivo (a diferencia de un directorio) y tiene una extensión .csv. ($ _ se refiere al parámetro, cuando está dentro de su bloque de secuencias de comandos). También puede pasar bloques de secuencias de comandos de varias líneas mucho más grandes si se requiere ese nivel, o usar varios bloques de secuencias de comandos como lo hice aquí. Es extremadamente útil, y hace que las funciones limpias y agradables y las excepciones intuitivas.
Si tengo una función que acepta más de un parámetro de cadena, el primer parámetro parece obtener todos los datos asignados y los parámetros restantes se pasan como vacíos.
Un script de prueba rápida:
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test("ABC", "DEF")
La salida generada es
$arg1 value: ABC DEF
$arg2 value:
La salida correcta debe ser:
$arg1 value: ABC
$arg2 value: DEF
Esto parece ser consistente entre v1 y v2 en múltiples máquinas, así que obviamente, estoy haciendo algo mal. ¿Alguien puede señalar exactamente qué?
Debido a que esta es una pregunta frecuente, quiero mencionar que una función de PowerShell debe usar verbos aprobados ( nombre- nombre). También puedes especificar cosas como si el parámetro es obligatorio y la posición del parámetro:
function Test-Script
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string]$arg1,
[Parameter(Mandatory=$true, Position=1)]
[string]$arg2
)
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Para pasar el parámetro a la función, puede usar la posición :
Test-Script "Hello" "World"
O bien, especifique el nombre del parámetro:
Test-Script -arg1 "Hello" -arg2 "World"
No usa paréntesis como lo hace cuando llama a una función dentro de C #.
Recomendaría pasar siempre los nombres de los parámetros cuando se usa más de un parámetro, ya que es más legible .
Digo lo siguiente antes:
El problema común es usar la forma singular $arg
, que es incorrecta.
Siempre debe ser plural como $args
.
El problema no es eso.
De hecho, $arg
puede ser cualquier otra cosa. El problema fue el uso de la coma y las paréntesis.
Ejecuto el siguiente código que funcionó y la salida sigue:
Código:
Function Test([string]$var1, [string]$var2)
{
Write-Host "`$var1 value: $var1"
Write-Host "`$var2 value: $var2"
}
Prueba "ABC" "DEF"
Salida:
Valor de $ var1: Valor de ABC $ var2: DEF
Los parámetros en las llamadas a funciones en PowerShell (todas las versiones) están separados por espacios, no por comas. Además, los paréntesis son totalmente innecesarios y causarán un error de análisis en PowerShell 2.0 (o posterior) si Set-StrictMode
está activo. Los argumentos entre paréntesis se utilizan únicamente en los métodos .NET.
function foo($a, $b, $c) {
"a: $a; b: $b; c: $c"
}
ps> foo 1 2 3
a: 1; b: 2; c: 3
No sé qué estás haciendo con la función, pero echa un vistazo a la palabra clave ''param''. Es un poco más potente para pasar parámetros a una función y lo hace más fácil de usar. A continuación se muestra un enlace a un artículo demasiado complejo de Microsoft al respecto. No es tan complicado como suena el artículo. Uso de parámetros
Además, aquí hay un ejemplo de un thread en este sitio:
Echale un vistazo.
Puede llamar a las funciones de PowerShell sin el paréntesis y sin usar la coma como separador. Trate de usar:
test "ABC" "DEF"
En PowerShell, la coma (,) es un operador de matriz, por ejemplo
$a = "one", "two", "three"
Establece $ a una matriz con tres valores.
Puede pasar parámetros en funciones como esta también.
function FunctionName()
{
Param ([string]$ParamName);
#Operations
}
Si eres un desarrollador de C # / Java / C ++ / Ruby / Python / Pick-A-Language-From-This-Century y quieres llamar a tu función con comas, porque eso es lo que siempre has hecho, entonces necesitas algo. Me gusta esto:
$myModule = new-module -ascustomobject {
function test($arg1, $arg2) {
echo "arg1 = $arg1, and arg2 = $arg2"
}
}
Ahora llama:
$myModule.test("ABC", "DEF")
y verás
arg1 = ABC, and arg2 = DEF
Si intentas:
PS > Test("ABC", "GHI") ("DEF")
usted obtiene:
$arg1 value: ABC GHI
$arg2 value: DEF
Para que veas que el paréntesis separa los parámetros.
Si intentas:
PS > $var = "C"
PS > Test ("AB" + $var) "DEF"
usted obtiene:
$arg1 value: ABC
$arg2 value: DEF
Ahora puede encontrar alguna utilidad inmediata del paréntesis (un espacio no se convertirá en un separador para el siguiente parámetro), en cambio, tiene una función eval.
Si no sabe (o le importa) cuántos argumentos pasará a la función, también podría usar un enfoque muy simple como;
Código :
function FunctionName()
{
Write-Host $args
}
Eso imprimiría todos los argumentos. Por ejemplo:
FunctionName a b c 1 2 3
Salida
a b c 1 2 3
Encuentro esto particularmente útil cuando se crean funciones que usan comandos externos que podrían tener muchos parámetros diferentes (y opcionales), pero se basan en dicho comando para proporcionar comentarios sobre errores de sintaxis, etc.
Aquí hay otro ejemplo del mundo real (crear una función para el comando tracert, que odio tener que recordar el nombre truncado);
Código :
Function traceroute
{
Start-Process -FilePath "$env:systemroot/system32/tracert.exe" -ArgumentList $args -NoNewWindow
}
Ya se ha proporcionado la respuesta correcta, pero este problema parece ser lo suficientemente frecuente como para justificar algunos detalles adicionales para aquellos que desean comprender las sutilezas. Habría agregado esto solo como un comentario, pero quería incluir una ilustración: arranqué este cuadro de referencia rápida en las funciones de PowerShell. Esto supone que la firma de la función f es f($a, $b, $c)
:
Por lo tanto, se puede llamar a una función con parámetros posicionales separados por espacios o parámetros nombrados independientes del orden. Los otros escollos revelan que debe tener en cuenta las comas, los paréntesis y los espacios en blanco.
Para obtener más información, consulte mi artículo Down the Rabbit Hole: un estudio sobre líneas de distribución , funciones y parámetros de PowerShell que se acaba de publicar en Simple-Talk.com. El artículo también contiene un enlace al gráfico de referencia rápida / muro.
Function Test {
Param([string]$arg1, [string]$arg2)
Write-Host $arg1
Write-Host $arg2
}
Esta es la declaración de parámetros adecuada https://technet.microsoft.com/en-us/library/dd347600.aspx
Y de hecho funciona
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test "ABC" "DEF"
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test("ABC") ("DEF")