Como passar parâmetros para uma função?

11

Preciso processar uma cópia de trabalho SVN em um script PS, mas tenho problemas para passar argumentos para funções. Aqui está o que eu tenho:

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] $_}

Eu quero passar $arg[0]como $arg1para foo, e $arg[1]como $arg2. No entanto, ele não funciona, por algum motivo, $arg1está sempre vazio:

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: O "blah"parâmetro não é passado como $arg1.

Estou absolutamente certo de que isso é algo hilariante simples (eu apenas comecei a fazer PS e ainda me sinto muito desajeitado), mas bati minha cabeça contra isso há mais de uma hora e não consigo encontrar nada.

sbi
fonte

Respostas:

2

A $arg[]matriz parece perder o escopo dentro do 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
fonte
Eu poderia aceitar qualquer uma das três respostas que recebi até agora, mas vou escolher essa porque mostra o que acabei fazendo.
S7
10

O motivo pelo qual $ args [0] não está retornando nada no objeto foreach é que $ args é uma variável automática que leva parâmetros sem nome e sem correspondência para um comando e o objeto foreach é um novo comando. Não existem parâmetros incomparáveis ​​para o bloco do processo, portanto $ args [0] é nulo.

Uma coisa que pode ajudar é que seus scripts podem ter parâmetros, assim como funções.

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 $_}

À medida que você começa a desejar mais funcionalidade de seus parâmetros, consulte uma postagem de blog que escrevi sobre a progressão de parâmetros de $ args para os parâmetros avançados atuais que podemos usar agora.

Steven Murawski
fonte
Blah. Razões como essa são a razão pela qual evito incorporar como Foreach-Object a favor do uso da boa e velha construção de loop foreach bruto.
Trevor Sullivan
Ah ok. Isso eu entendo agora. Droga, isso parece bastante contra-intuitivo!
Sb 06/07
3

Tente algo como isto:

# 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
fonte
Que "forçar itens a serem retornados como uma matriz" é algo que devo acrescentar. Obrigado pela dica!
Sbi 06/07
Sim, é preciso ter cuidado se você conseguir apenas um único item de volta - ao lançá-lo explicitamente como uma matriz, você obtém resultados consistentes, para que você possa iterá-lo usando foreach.
Trevor Sullivan