Wie übergebe ich Parameter an eine Funktion?

11

Ich muss eine SVN-Arbeitskopie in einem PS-Skript verarbeiten, habe jedoch Probleme, Argumente an Funktionen zu übergeben. Folgendes habe ich:

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

Ich möchte weitergeben , $arg[0]wie $arg1zu foo, und $arg[1]wie $arg2. Es funktioniert jedoch nicht, aus irgendeinem Grund $arg1ist es immer leer:

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>

Hinweis: Der "blah"Parameter wird nicht als übergeben $arg1.

Ich bin mir absolut sicher, dass dies etwas unglaublich Einfaches ist (ich habe gerade erst mit PS angefangen und fühle mich immer noch sehr ungeschickt), aber ich habe jetzt seit mehr als einer Stunde meinen Kopf dagegen geschlagen und kann nichts finden.

sbi
quelle

Antworten:

2

Das $arg[]Array scheint den Bereich innerhalb des ForEach-Objekts zu verlieren .

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
quelle
Ich könnte jede der drei Antworten akzeptieren, die ich bisher erhalten habe, aber ich werde diese auswählen, weil dies zeigt, was ich letztendlich getan habe.
sbi
10

Der Grund, warum $ args [0] nichts im foreach-Objekt zurückgibt, ist, dass $ args eine automatische Variable ist, die unbenannte, nicht übereinstimmende Parameter zu einem Befehl nimmt, und das foreach-Objekt ein neuer Befehl ist. Es gibt keine nicht übereinstimmenden Parameter für den Prozessblock, daher ist $ args [0] null.

Eine Sache, die helfen kann, ist, dass Ihre Skripte Parameter haben können, genau wie Funktionen.

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

Wenn Sie mehr Funktionalität für Ihre Parameter wünschen, sollten Sie sich einen Blog-Beitrag ansehen, den ich über den Fortschritt der Parameter von $ args zu den aktuellen erweiterten Parametern geschrieben habe, die wir jetzt verwenden können.

Steven Murawski
quelle
Blah. Gründe wie diese sind, warum ich Einbauten wie Foreach-Object vermeide, um das gute alte rohe foreach-Schleifenkonstrukt zu verwenden.
Trevor Sullivan
Ah, ok. Das verstehe ich jetzt. Verdammt, das scheint allerdings ziemlich eingängig zu sein!
sbi
3

Versuchen Sie so etwas:

# 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
quelle
Das "Erzwingen der Rückgabe von Elementen als Array" sollte ich in der Tat hinzufügen. Danke für den Tipp!
sbi
Ja, Sie müssen vorsichtig sein, wenn Sie nur ein einzelnes Element zurückerhalten. Wenn Sie es explizit als Array umwandeln, erhalten Sie konsistente Ergebnisse, sodass Sie es mit iterieren können foreach.
Trevor Sullivan