Jeśli mam funkcję, która akceptuje więcej niż jeden parametr łańcuchowy, pierwszy parametr wydaje się otrzymać wszystkie dane przypisane do niego, a pozostałe parametry są przekazywane jako puste.
Szybki skrypt testowy:
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test("ABC", "DEF")
Wygenerowane dane wyjściowe to
$arg1 value: ABC DEF
$arg2 value:
Prawidłowe wyjście powinno być:
$arg1 value: ABC
$arg2 value: DEF
Wydaje się, że jest to spójne między wersją 1 i 2 na wielu komputerach, więc oczywiście robię coś złego. Czy ktoś może dokładnie wskazać, co?
powershell
Nasir
źródło
źródło
Test "ABC" "DEF"
Odpowiedzi:
Parametry wywołań funkcji w programie PowerShell (wszystkie wersje) są rozdzielane spacjami, a nie przecinkami . Ponadto nawiasy są całkowicie niepotrzebne i spowodują błąd analizy w programie PowerShell 2.0 (lub nowszym), jeśli
Set-StrictMode
jest aktywny. Argumenty w nawiasach są używane tylko w metodach .NET.źródło
(1,2,3)
do funkcji jest skutecznie traktowane jako tablica; pojedynczy argument. Jeśli chcesz użyć argumentów w stylu metody OO, użyj modułów:$m = new-module -ascustomobject { function Add($x,$y) { $x + $y } }; $m.Add(1,1)
Powershell
jest językiem powłoki i języki powłoki często używają spacji jako separatora tokenów. Nie powiedziałbym, żePowershell
to jest inny tutaj, to prawda zgodne z innymi domyślny system powłok takich jakcmd
,sh
,bash
itpPodano już prawidłową odpowiedź, ale ten problem wydaje się na tyle rozpowszechniony, że uzasadnia dodatkowe szczegóły dla osób chcących zrozumieć subtelności.
Dodałbym to tylko jako komentarz, ale chciałem załączyć ilustrację - oderwałem to od mojej skróconej tabeli funkcji programu PowerShell. Zakłada się, że sygnatura funkcji f to
f($a, $b, $c)
:W ten sposób można wywołać funkcję z parametrami pozycyjnymi oddzielonymi spacjami lub nazwanymi parametrami niezależnymi od kolejności . Inne pułapki ujawniają, że musisz być świadomy przecinków, nawiasów i białych znaków.
Więcej informacji można znaleźć w moim artykule W dół króliczej nory: studium potoków, funkcji i parametrów programu PowerShell . Artykuł zawiera również link do szybkiego odniesienia / tabeli ściennej.
źródło
Jest tu kilka dobrych odpowiedzi, ale chciałem zwrócić uwagę na kilka innych rzeczy. Parametry funkcji są w rzeczywistości miejscem, w którym świeci PowerShell. Na przykład możesz mieć parametry nazwane lub pozycyjne w funkcjach zaawansowanych, takich jak:
Następnie możesz albo wywołać go, podając nazwę parametru, albo możesz po prostu użyć parametrów pozycyjnych, ponieważ je wyraźnie zdefiniowałeś. Więc którykolwiek z nich działałby:
Pierwszy przykład działa, mimo że
Name
podany jest drugi, ponieważ jawnie użyliśmy nazwy parametru. Drugi przykład działa jednak w oparciu o pozycję, więcName
musiałby być pierwszy. Jeśli to możliwe, zawsze staram się zdefiniować pozycje, aby obie opcje były dostępne.PowerShell ma również możliwość definiowania zestawów parametrów. Wykorzystuje to zamiast przeciążania metod i znów jest całkiem przydatne:
Teraz funkcja przyjmie nazwę lub identyfikator, ale nie jedno i drugie. Możesz użyć ich pozycjonować lub według nazwy. Ponieważ są innego typu, PowerShell to rozwiąże. Wszystko to działałoby:
Możesz także przypisać dodatkowe parametry do różnych zestawów parametrów. (To był oczywiście dość prosty przykład.) Wewnątrz funkcji można określić, który zestaw parametrów został użyty za pomocą właściwości $ PsCmdlet.ParameterSetName. Na przykład:
Następnie, w powiązanej notatce dodatkowej, istnieje również sprawdzanie poprawności parametrów w PowerShell. Jest to jedna z moich ulubionych funkcji PowerShell i sprawia, że kod w twoich funkcjach jest bardzo czysty. Istnieje wiele walidacji, których możesz użyć. Oto kilka przykładów:
W pierwszym przykładzie ValidatePattern akceptuje wyrażenie regularne, które zapewnia, że podany parametr odpowiada oczekiwaniom. Jeśli nie, zgłaszany jest intuicyjny wyjątek, który mówi dokładnie, co jest nie tak. W tym przykładzie „Coś” działałoby dobrze, ale „Lato” nie przejdzie weryfikacji.
ValidateRange zapewnia, że wartość parametru mieści się w zakresie oczekiwanym dla liczby całkowitej. Więc 10 lub 99 działałoby, ale 101 rzuciłoby wyjątek.
Kolejnym przydatnym jest ValidateSet, który pozwala jawnie zdefiniować tablicę dopuszczalnych wartości. W przypadku wprowadzenia czegoś innego zostanie zgłoszony wyjątek. Są też inne, ale prawdopodobnie najbardziej przydatnym jest ValidateScript. To wymaga bloku skryptu, który musi mieć wartość $ true, więc niebo jest granicą. Na przykład:
W tym przykładzie mamy pewność, że nie tylko istnieje $ Path, ale jest to plik (w przeciwieństwie do katalogu) i ma rozszerzenie .csv. ($ _ odnosi się do parametru, gdy znajduje się w twoim bloku skryptu.) Możesz również przekazać znacznie większe, wieloliniowe bloki skryptu, jeśli ten poziom jest wymagany, lub użyć wielu bloków skryptu, jak ja tutaj. Jest niezwykle przydatny i zapewnia ładne czyste funkcje i intuicyjne wyjątki.
źródło
My_Function -NamedParamater "ParamValue"
stylu wywołania funkcji. Jest to wzorzec, który powinien podążać więcej kodu skryptu PS w celu zapewnienia czytelności.Funkcje programu PowerShell wywoływane są bez nawiasów i bez przecinka jako separatora. Spróbuj użyć:
W PowerShell przecinek (,) jest operatorem tablicowym, np
Ustawia
$a
na tablicę z trzema wartościami.źródło
źródło
Jeśli jesteś programistą C # / Java / C ++ / Ruby / Python / Pick-A-Language-From-This-Century i chcesz wywołać swoją funkcję przecinkami, ponieważ zawsze tak robiłeś, potrzebujesz czegoś lubię to:
Teraz zadzwoń:
i zobaczysz
źródło
Jeśli nie wiesz (lub nie obchodzi Cię), ile argumentów przekażesz funkcji, możesz również zastosować bardzo proste podejście;
Kod :
To wypisze wszystkie argumenty. Na przykład:
Wynik
Uważam to za szczególnie przydatne podczas tworzenia funkcji, które używają poleceń zewnętrznych, które mogą mieć wiele różnych (i opcjonalnych) parametrów, ale polegają na tym poleceniu, aby przekazywać opinie na temat błędów składniowych itp.
Oto kolejny przykład ze świata rzeczywistego (tworzenie funkcji do polecenia tracert, której nienawidzę, pamiętając skróconą nazwę);
Kod :
źródło
Jeśli spróbujesz:
dostajesz:
Widzisz więc, że nawiasy oddzielają parametry
Jeśli spróbujesz:
dostajesz:
Teraz możesz znaleźć natychmiastową użyteczność nawiasów - spacja nie stanie się separatorem dla następnego parametru - zamiast tego masz funkcję eval.
źródło
@
) przed czołowymi paren jak pustego tablicy:@()
; Tablica lub dwoma numerami:@(1, 2)
.Ponieważ jest to często zadawane pytanie, chcę wspomnieć, że należy użyć funkcji PowerShell zatwierdzonych czasowników ( rzeczownik-czasownik jako nazwa funkcji). Czasownikowa część nazwy identyfikuje akcję wykonywaną przez cmdlet. Rzeczownikowa część nazwy identyfikuje byt, na którym wykonywana jest akcja. Ta reguła upraszcza korzystanie z poleceń cmdlet dla zaawansowanych użytkowników PowerShell.
Możesz także określić takie rzeczy, jak parametr obowiązkowy i pozycję parametru:
Aby przekazać parametr do funkcji, możesz użyć pozycji :
Lub określasz parametr nazwę :
Nie używasz nawiasów jak w przypadku wywoływania funkcji w języku C #.
Zalecam, aby zawsze podawać nazwy parametrów, gdy jest używany więcej niż jeden parametr, ponieważ jest to bardziej czytelne .
źródło
Get-Node
cmdlet. Będzie dla nas jasne, że musimy się odwoływaćGet-Node
, nieRetrieve-Node
, aniReceive-Node
, ani .....Nie wiem, co robisz z funkcją, ale spójrz na użycie słowa kluczowego „param”. Jest o wiele bardziej wydajny do przekazywania parametrów do funkcji i czyni go bardziej przyjaznym dla użytkownika. Poniżej znajduje się link do zbyt złożonego artykułu Microsoft na ten temat. To nie jest tak skomplikowane, jak brzmi ten artykuł.
Użycie Param
Oto przykład z pytania na tej stronie:
Sprawdź to.
źródło
źródło
Powiedziałem wcześniej:
Częstym problemem jest używanie formy pojedynczej
$arg
, co jest niepoprawne. Zawsze powinno być w liczbie mnogiej jak$args
.Problem nie jest taki. W rzeczywistości
$arg
może być cokolwiek innego. Problem polegał na użyciu przecinka i nawiasów.Uruchamiam następujący kod, który działał, a dane wyjściowe są następujące:
Kod:
Test „ABC” „DEF”
Wynik:
źródło
To jest właściwa
params
deklaracja.Zobacz about_Functions_Advanced_Parameters .
I to naprawdę działa.
źródło
Możesz przekazać parametry w funkcji takiej jak ta:
źródło
Nie widzę tu o tym wspominanych, ale splatanie argumentów jest przydatną alternatywą i staje się szczególnie przydatne, jeśli budujesz argumenty do polecenia dynamicznie (w przeciwieństwie do używania
Invoke-Expression
). Możesz splatać się z tablicami dla argumentów pozycyjnych i tablicami skrótów dla nazwanych argumentów. Oto kilka przykładów:Ikona z tablicami (argumenty pozycyjne)
Połączenie testowe z argumentami pozycyjnymi
Z rozpryskiwaniem szyku
Ikona z Hashtable (nazwane argumenty)
Połączenie testowe z nazwanymi argumentami
Z Hashtable Splatting
Argumenty pozycyjne i nazwane jednocześnie
Połączenie testowe z argumentami pozycyjnymi i nazwanymi
Splatting Array i Hashtables Razem
źródło