Comment passer des paramètres à une fonction?


11

J'ai besoin de traiter une copie de travail SVN dans un script PS, mais j'ai du mal à passer des arguments aux fonctions. Voici ce que j'ai:

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

Je veux passer $arg[0]comme $arg1à foo, et $arg[1]que $arg2. Cependant, cela ne fonctionne pas, pour une raison quelconque, il $arg1est toujours vide:

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>

Remarque: Le "blah"paramètre n'est pas transmis en tant que $arg1.

Je suis absolument sûr que c'est quelque chose de hilarante simple (je viens juste de commencer à faire du PS et je me sens toujours très maladroit), mais je me suis cogné la tête contre cela depuis plus d'une heure maintenant, et je ne trouve rien.

Réponses:


2

Le $arg[]tableau semble perdre la portée à l'intérieur de 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)"
}

Je pourrais accepter n'importe laquelle des trois réponses que j'ai obtenues jusqu'à présent, mais je vais choisir celle-ci, car cela montre ce que j'ai fini par faire.
— sbi

10

La raison pour laquelle $ args [0] ne renvoie rien dans foreach-object est que $ args est une variable automatique qui prend des paramètres sans nom et sans correspondance dans une commande et foreach-object est une nouvelle commande. Il n'y a aucun paramètre inégalé pour le bloc de processus, donc $ args [0] est nul.

Une chose qui peut vous aider est que vos scripts peuvent avoir des paramètres, tout comme les fonctions.

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

Alors que vous commencez à vouloir plus de fonctionnalités de vos paramètres, vous voudrez peut-être consulter un article de blog que j'ai écrit sur la progression des paramètres de $ args vers les paramètres avancés actuels que nous pouvons utiliser maintenant.


Blabla. Des raisons comme celle-ci expliquent pourquoi j'évite les incorporations comme Foreach-Object en faveur de l'utilisation de la bonne construction en boucle foreach brute.
— Trevor Sullivan

Ah ok. C'est ce que je comprends maintenant. Merde, cela semble assez contre-intuitif, cependant!
— sbi

3

Essayez quelque chose comme ceci:

# 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
}

Que "forcer les éléments à être retournés sous forme de tableau" est quelque chose que je devrais en effet ajouter. Merci pour l'astuce!
— sbi

Ouais, je dois faire attention si vous ne récupérez qu'un seul élément - en le castant explicitement comme un tableau, vous obtenez des résultats cohérents, vous pouvez donc itérer dessus en utilisant foreach.
— Trevor Sullivan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.