¿Cómo pasar parámetros a una función?


11

Necesito procesar una copia de trabajo SVN en un script PS, pero tengo problemas para pasar argumentos a las funciones. Esto es lo que tengo:

function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $($args[0])"
echo "1: $($args[1])"
$items = get-childitem $args[1] 
$items | foreach-object -process {foo $args[0] $_}

Quiero pasar $arg[0]como $arg1a foo, y $arg[1]como $arg2. Sin embargo, no funciona, por alguna razón $arg1siempre está vacío:

PS C:\Users\sbi> .\test.ps1 blah .\Dropbox
0: blah
1: .\Dropbox
C:\Users\sbi\Dropbox\Photos
C:\Users\sbi\Dropbox\Public
C:\Users\sbi\Dropbox\sbi
PS C:\Users\sbi>

Nota: El "blah"parámetro no se pasa como $arg1.

Estoy absolutamente seguro de que esto es algo hilarantemente simple (recién comencé a hacer PS y todavía me siento muy torpe), pero me he golpeado la cabeza contra esto durante más de una hora y no puedo encontrar nada.

Respuestas:


2

La $arg[]matriz parece perder alcance dentro del ForEach-Object .

function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $($args[0])"
echo "1: $($args[1])"
$zero = $args[0]
$one = $args[1]
$items = get-childitem $args[1] 
$items | foreach-object {
    echo "inner 0: $($zero)"
    echo "inner 1: $($one)"
}

Podría aceptar cualquiera de las tres respuestas que obtuve hasta ahora, pero elegiré esta, porque esto muestra lo que terminé haciendo.
sbi

10

La razón por la que $ args [0] no está devolviendo nada en el objeto foreach es que $ args es una variable automática que toma parámetros sin nombre y no coincidentes a un comando y el objeto foreach es un comando nuevo. No hay parámetros no coincidentes para el bloque de proceso, por lo que $ args [0] es nulo.

Una cosa que puede ayudar es que sus scripts pueden tener parámetros, al igual que las funciones.

param ($SomeText, $SomePath)
function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $SomeText"
echo "1: $SomePath"
$items = get-childitem $SomePath
$items | foreach-object -process {foo $SomeText $_}

A medida que comience a querer más funcionalidad de sus parámetros, puede consultar una publicación de blog que escribí sobre la progresión de parámetros desde $ args a los parámetros avanzados actuales que podemos usar ahora.


Paja. Razones como esta son las razones por las que evito las incorporaciones como Foreach-Object a favor del uso de la buena construcción de bucles foreach sin formato.
Trevor Sullivan

Ah ok. Esto lo entiendo ahora. ¡Maldición, eso parece bastante contradictorio, sin embargo!
sbi

3

Intenta algo como esto:

# Use an advanced function
function foo
{
  [CmdletBinding()]
  param (
      [string] $arg1
    , [string] $arg2
  )

  Write-Host -Object $arg1;
  Write-Host -Object $arg2;
}

# Create array of "args" to emulate passing them in from command line.
$args = @('blah', 'c:\test');

echo "0: $($args[0])"
echo "1: $($args[1])"

# Force items to be returned as an array, in case there's only 1 item returned
$items = @(Get-ChildItem -Path $args[1]);
Write-Host -Object "There are $($items.Count) in `$items";

# Iterate over items found in directory
foreach ($item in $items) {
    foo -Arg1 $args[0] -Arg2 $item.FullName
}

Ese "forzar que los elementos se devuelvan como una matriz" es algo que debería agregar. ¡Gracias por la pista!
sbi

Sí, tengo que tener cuidado si solo recuperas un solo elemento: al lanzarlo explícitamente como una matriz, obtienes resultados consistentes, por lo que puedes iterar sobre él usando foreach.
Trevor Sullivan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.