577 Stimmen

Wie übergebe ich mehrere Parameter an eine Funktion in PowerShell?

Wenn ich eine Funktion habe, die mehr als einen String-Parameter akzeptiert, scheint der erste Parameter alle zugewiesenen Daten zu erhalten, während die übrigen Parameter als leer übergeben werden.

Ein einfaches Testskript:

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 Wert: $arg1"
    Write-Host "`$arg2 Wert: $arg2"
}

Test("ABC", "DEF")

Die generierte Ausgabe ist

$arg1 Wert: ABC DEF
$arg2 Wert: 

Die korrekte Ausgabe sollte sein:

$arg1 Wert: ABC
$arg2 Wert: DEF

Dies scheint auf mehreren Maschinen zwischen v1 und v2 konsistent zu sein, daher mache ich offensichtlich etwas falsch. Kann mir jemand genau zeigen, was?

8 Stimmen

Du rufst einfach so an: Test "ABC" "DEF"

2 Stimmen

Meiner bescheidenen Meinung nach zeigt die Tatsache, dass diese Frage und Antwort so viele positive Bewertungen haben, dass die aktuelle Implementierung.... nicht intuitiv ist.

15voto

Martin Brandl Punkte 51333

Weil dies eine häufig angesehene Frage ist, möchte ich erwähnen, dass eine PowerShell-Funktion genehmigte Verben verwenden sollte (Verb-Nomen als Funktionsnamen). Der Verb-Teil des Namens identifiziert die Aktion, die das Cmdlet ausführt. Der Nomen-Teil des Namens identifiziert die Entität, auf die die Aktion angewendet wird. Diese Regel vereinfacht die Verwendung Ihrer Cmdlets für fortgeschrittene PowerShell-Benutzer.

Sie können auch Dinge wie angeben, ob der Parameter obligatorisch ist und die Position des Parameters:

function Test-Script
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$arg1,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$arg2
    )

    Write-Host "`$arg1 Wert: $arg1"
    Write-Host "`$arg2 Wert: $arg2"
}

Um den Parameter an die Funktion zu übergeben, können Sie entweder die Position verwenden:

Test-Script "Hallo" "Welt"

Oder Sie geben den Parameternamen an:

Test-Script -arg1 "Hallo" -arg2 "Welt"

Sie verwenden keine Klammern wie bei einem Funktionsaufruf in C#.


Ich würde empfehlen, bei der Verwendung von mehr als einem Parameter immer die Parameternamen anzugeben, da dies lesbarer ist.

0 Stimmen

Zur Information: Der Link zur genehmigten Verbenliste funktioniert nicht mehr, ist aber jetzt hier zu finden - learn.microsoft.com/de-de/powershell/developer/cmdlet/…

0 Stimmen

@KeithLangmead Vielen Dank, Keith, ich habe auch meine Antwort aktualisiert.

1 Stimmen

"Verb-Noun" wie in sowohl Verb als auch Nomen großgeschrieben? Vielleicht die Antwort ändern, um dies expliziter darzustellen?

14voto

Ryan Shillington Punkte 19095

Wenn Sie ein Entwickler für C# / Java / C++ / Ruby / Python / Pick-A-Language-From-This-Century sind und Ihre Funktion mit Kommas aufrufen möchten, weil Sie das schon immer getan haben, dann benötigen Sie so etwas:

$myModule = New-Module -ascustomobject { 
    function test($arg1, $arg2) { 
        echo "arg1 = $arg1, and arg2 = $arg2"
    }
}

Jetzt rufen Sie auf:

$myModule.test("ABC", "DEF")

und Sie sehen

arg1 = ABC, and arg2 = DEF

3 Stimmen

Java, C++, Ruby, und Python sind nicht aus diesem Jahrhundert (nur C#), vorausgesetzt, der gregorianische Kalender (obwohl sich einige mehr entwickelt haben als andere).

0 Stimmen

Heh. @PeterMortensen deine Argumentation ist, dass ich sagen sollte, "Wähle eine Sprache aus diesem Jahrhundert oder dem letzten"? :-)

12voto

Draino Punkte 121

Wenn Sie nicht wissen (oder nicht interessiert sind), wie viele Argumente Sie an die Funktion übergeben werden, können Sie auch einen sehr einfachen Ansatz wie folgt verwenden:

Code:

function FunctionName()
{
    Write-Host $args
}

Dies würde alle Argumente ausgeben. Zum Beispiel:

FunctionName a b c 1 2 3

Output

a b c 1 2 3

Ich finde dies besonders nützlich beim Erstellen von Funktionen, die externe Befehle verwenden, die viele verschiedene (und optionale) Parameter haben könnten, sich aber auf diesen Befehl verlassen, um Feedback zu Syntaxfehlern usw. zu geben.

Hier ist ein weiteres Beispiel aus der Praxis (Erstellen einer Funktion für den tracert-Befehl, dessen abgekürzten Namen ich nicht gerne behalten muss):

Code:

Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}

8voto

RaSor Punkte 665

Wenn du es versuchst:

PS > Test("ABC", "GHI") ("DEF")

erhältst du:

$arg1 Wert: ABC GHI
$arg2 Wert: DEF

Also siehst du, dass die Klammern die Parameter trennen


Wenn du es versuchst:

PS > $var = "C"
PS > Test ("AB" + $var) "DEF"

erhältst du:

$arg1 Wert: ABC
$arg2 Wert: DEF

Jetzt könntest du einige unmittelbare Nützlichkeit der Klammern finden - ein Leerzeichen wird nicht zum Separator für den nächsten Parameter - stattdessen hast du eine Eval-Funktion.

4 Stimmen

Klammern trennen keine Parameter. Sie definieren ein Array.

1 Stimmen

Klammern definieren kein Array, sondern eine Gruppe, die PowerShell als Array interpretieren kann. Arrays werden mit einem @-Zeichen (@) vor der führenden Klammer definiert, wie dieses leere Array: @(); oder dieses Array mit zwei Zahlen: @(1, 2).

7voto

Bender Punkte 17221

Ich sehe es hier nicht erwähnt, aber splatting deiner Argumente ist eine nützliche Alternative und wird besonders nützlich, wenn du die Argumente zu einem Befehl dynamisch aufbaust (anstatt Invoke-Expression zu verwenden). Du kannst mit Arrays für positionale Argumente und Hashtables für benannte Argumente splatten. Hier sind einige Beispiele:

Hinweis: Du kannst positionale Splat-Arrays mit externen Befehlsargumenten relativ leicht verwenden, aber benannte Splat-Arrays sind mit externen Befehlen weniger nützlich. Sie funktionieren, aber das Programm muss Argumente im Format -Schlüssel:Wert akzeptieren, da jeder Parameter zu den Hashtable-Schlüssel/Wert-Paaren gehört. Ein Beispiel für solche Software ist der choco-Befehl des Chocolatey-Paketmanagers für Windows.

Splitten mit Arrays (Positionale Argumente)

Test-Connection mit positionalen Argumenten

Test-Connection www.google.com localhost

Mit Array-Splitten

$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentArray

Beachte, dass wir beim Splitten auf die gesplittete Variable mit einem @ anstelle von einem $ verweisen. Das gilt auch für das Splitten mit einer Hashtable.

Splitten mit Hashtable (Benannte Argumente)

Test-Connection mit benannten Argumenten

Test-Connection -ComputerName www.google.com -Source localhost

Mit Hashtable-Splitten

$argumentHash = @{
  ComputerName = 'www.google.com'
  Source = 'localhost'
}
Test-Connection @argumentHash

Positionale und benannte Argumente gleichzeitig splitten

Test-Connection mit sowohl positionalen als auch benannten Argumenten

Test-Connection www.google.com localhost -Count 1

Arrays und Hashtables zusammen splitten

$argumentHash = @{
  Count = 1
}
$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentHash @argumentArray

0 Stimmen

Dies hat für mich nicht funktioniert, aber stattdessen habe ich etwas Ähnliches gemacht $Results = GetServerInformation $Servers $ServerNames

0 Stimmen

Splatting ist die Syntax, die verwendet wird, um ein Hashtable oder Array zu nehmen und diese als benannte Argumente oder positionale Argumente an ein anderes Kommando weiterzugeben, anstelle die Argumente direkt an das Kommando zu übergeben, wie Sie es getan haben. Wenn Sie eine Frage zu Ihrem nicht funktionierenden Splat posten, kann jemand sein Licht auf Ihr spezifisches Problem werfen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X