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