¿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.

sbi
fuente

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)"
}
Justin Dearing
fuente
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.

Steven Murawski
fuente
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
}
Trevor Sullivan
fuente
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