複数の文字列パラメータを受け取る関数がある場合、最初のパラメータはそれに割り当てられているすべてのデータを取得するように見え、残りのパラメータは空として渡されます。
簡単なテストスクリプト
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test("ABC", "DEF")
生成された出力は
$arg1 value: ABC DEF
$arg2 value:
正しい出力は次のようになります。
$arg1 value: ABC
$arg2 value: DEF
これは、複数のマシン上のv1とv2の間で一貫しているように見えるので、明らかに、私は何か問題を起こしています。誰もが正確に何を指摘できますか?
PowerShellの関数呼び出し(すべてのバージョン)のパラメーターは、スペースで区切られており、コンマで区切られていません。また、括弧はまったく不要なので、Set-StrictMode
がアクティブな場合、PowerShell 2.0以降では解析エラーが発生します。括弧で囲まれた引数は.NETメソッドでのみ使用されます。
function foo($a, $b, $c) {
"a: $a; b: $b; c: $c"
}
ps> foo 1 2 3
a: 1; b: 2; c: 3
正しい答えはすでに提供されていますが、この問題は微妙な部分を理解したい人のためのいくつかの追加の詳細を正当化するのに十分普及しているようです。これは単なるコメントとして追加したはずですが、イラストを含めたいと思いました。PowerShellの機能に関するクイックリファレンスチャートからこれを切り離しました。これは関数fのシグネチャがf($a, $b, $c)
であると仮定します。
したがって、スペースで区切られた 位置 パラメータまたは順序に依存しない 名前付き parametersを使用して関数を呼び出すことができます。他の落とし穴は、あなたがカンマ、括弧、 と 空白を認識する必要があることを明らかにしています。
さらに読むために私の記事を参照してください うさぎの穴を下って:PowerShellのパイプライン、関数、およびパラメーターの研究 Simple-Talk.comで公開されたこの記事にはクイックリファレンス/ウォールチャートへのリンクも含まれています。
PowerShell関数は、括弧なしで、また区切り文字としてコンマを使用せずに呼び出します。試してみてください。
test "ABC" "DEF"
PowerShellでは、コンマ(、)は配列演算子です。
$a = "one", "two", "three"
$ aを3つの値を持つ配列に設定します。
ここにいくつかの良い答えがありますが、私は他にもいくつか指摘したいと思いました。関数パラメータは、実際にはPowerShellが輝く場所です。たとえば、次のような高度な機能では、名前付きパラメータまたは位置パラメータを使用できます。
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string] $Name,
[Parameter(Mandatory=$true, Position=1)]
[int] $Id
)
}
それからパラメータ名を指定してそれを呼び出すことも、明示的に定義したので単に位置パラメータを使用することもできます。それで、これらのどちらでもうまくいくでしょう:
Get-Something -Id 34 -Name "Blah"
Get-Something "Blah" 34
最初の例は、Nameが2番目に指定されていても機能します。これは、明示的にパラメータ名を使用したためです。ただし、2番目の例は位置に基づいて機能するため、Nameを最初に指定する必要があります。可能であれば、私は常にポジションを定義しようとしているので両方のオプションが利用可能です。
PowerShellには、パラメータセットを定義する機能もあります。メソッドのオーバーロードの代わりにこれを使用していますが、これも非常に便利です。
function Get-Something
{
[CmdletBinding(DefaultParameterSetName='Name')]
Param
(
[Parameter(Mandatory=$true, Position=0, ParameterSetName='Name')]
[string] $Name,
[Parameter(Mandatory=$true, Position=0, ParameterSetName='Id')]
[int] $Id
)
}
この関数は名前かIDのどちらかを取りますが、両方は取りません。あなたはそれらを位置的にあるいは名前で使うことができます。それらは異なるタイプなので、PowerShellはそれを理解します。だからこれらのすべてがうまくいくだろう
Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23
さまざまなパラメータセットに追加のパラメータを割り当てることもできます。 (これは明らかにかなり基本的な例です)関数内で、$ PsCmdlet.ParameterSetNameプロパティでどのパラメータセットが使用されたかを判断できます。例えば:
if($PsCmdlet.ParameterSetName -eq "Name")
{
Write-Host "Doing something with name here"
}
それから、関連するメモとして、PowerShellのパラメータ検証もあります。これは私のお気に入りのPowerShell機能の1つであり、関数内のコードを非常にきれいにします。あなたが使用できるたくさんの検証があります。いくつかの例は
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidatePattern('^Some.*')]
[string] $Name,
[Parameter(Mandatory=$true, Position=1)]
[ValidateRange(10,100)]
[int] $Id
)
}
最初の例では、ValidatePatternは、提供されたパラメータが期待しているものと一致することを保証する正規表現を受け入れます。そうでない場合は、直観的な例外がスローされ、何が問題なのか正確にわかります。したがって、その例では、「何か」はうまく機能しますが、「夏」は検証に合格しません。
ValidateRangeは、パラメーター値が整数として期待される範囲内にあることを確認します。したがって、10または99が動作しますが、101は例外をスローします。
もう1つの便利なものはValidateSetです。これを使用すると、許容値の配列を明示的に定義できます。何か他のものが入力された場合、例外がスローされます。他にもありますが、おそらく 最も有用な 1はValidateScriptです。これは$ trueと評価されなければならないスクリプトブロックをとるので、空が限界です。例えば:
function Get-Something
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
[ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
[string] $Path
)
}
この例では、$ Pathが存在するだけでなく、それがファイルであり(ディレクトリではなく)、拡張子が.csvであることが保証されています。このレベルが必要な場合は、はるかに大きい複数行のスクリプトブロックを渡すことも、ここで行ったように複数のスクリプトブロックを使用することもできます。それは非常に便利です、そしてきれいな関数と直感的な例外をきれいにします。
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test "ABC" "DEF"
あなたがC#/ Java/C++/Ruby/Python /今世紀からの言語を選ぶ開発者で、あなたが自分の関数をコンマで呼び出したいのなら、それがいつもしていることなので、何かが必要ですこのような:
$myModule = new-module -ascustomobject {
function test($arg1, $arg2) {
echo "arg1 = $arg1, and arg2 = $arg2"
}
}
今電話してください:
$myModule.test("ABC", "DEF")
そして見ますよ
arg1 = ABC, and arg2 = DEF
関数に渡す引数の数がわからない(または気にしない)場合は、次のような非常に単純な方法を使用することもできます。
コード :
function FunctionName()
{
Write-Host $args
}
それはすべての議論をプリントアウトするでしょう。例えば:
FunctionName a b c 1 2 3
出力
a b c 1 2 3
私はこれが特に有用であると思う。多くの異なる(そしてオプションの)パラメータを持つことができる外部コマンドを使う関数を作成するとき、構文エラーなどに関するフィードバックを提供するために前記コマンドに頼る.
これはもう一つの現実的な例です(tracertコマンドへの関数の作成、私は切り捨てられた名前を覚えておく必要はありません)。
コード :
Function traceroute
{
Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
あなたがしようとした場合:
PS > Test("ABC", "GHI") ("DEF")
あなたが得る:
$arg1 value: ABC GHI
$arg2 value: DEF
あなたがしようとした場合:
PS > $var = "C"
PS > Test ("AB" + $var) "DEF"
あなたが得る:
$arg1 value: ABC
$arg2 value: DEF
今すぐあなたは括弧のいくつかの即時の有用性を見つけることができた - スペースは次のパラメータのためのセパレータにならない - 代わりにあなたはeval関数を持っている。
これはよくある質問なので、PowerShell関数は 承認された動詞 (Verb-Noun)を関数名として使用する必要があります。また、パラメーターが必須およびパラメーターのposition
function Test-Script
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string]$arg1,
[Parameter(Mandatory=$true, Position=1)]
[string]$arg2
)
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
関数にパラメータを渡すには、position:)を使うことができます。
Test-Script "Hello" "World"
あるいはあなたは指定パラメータ名前:)
Test-Script -arg1 "Hello" -arg2 "World"
あなたはC#の中で関数を呼び出すときのように括弧を使わないでください。
複数のパラメータを使用する場合は、alwaysを渡すことをお勧めします。これはreadのためです。
Function Test([string]$arg1, [string]$arg2)
{
Write-Host "`$arg1 value: $arg1"
Write-Host "`$arg2 value: $arg2"
}
Test("ABC") ("DEF")
Function Test {
Param([string]$arg1, [string]$arg2)
Write-Host $arg1
Write-Host $arg2
}
これは正しいparams宣言です https://technet.Microsoft.com/ja-jp/library/dd347600.aspx
そしてそれは確かにうまくいく
私は先に次のように述べています。
よくある問題は単数形の$arg
を使うことですが、これは誤りです。
これは常に$args
のように複数形であるべきです。
問題ではありません。
実際、$arg
は他のものでもかまいません。問題は、コンマと括弧の使用でした。
私はうまくいった以下のコードを実行します、そして、出力は続きます:
コード:
Function Test([string]$var1, [string]$var2)
{
Write-Host "`$var1 value: $var1"
Write-Host "`$var2 value: $var2"
}
テスト "ABC" "DEF"
出力:
$ var1値:ABC $ var2値:DEF
ここでは触れていませんが、 飛び跳ねる あなたの引数は有効な代替手段であり、(Invoke-Expression
を使用するのではなく)動的にコマンドの引数を作成する場合に特に役立ちます。位置引数には配列を、名前付き引数にはハッシュテーブルを使用することができます。ここではいくつかの例を示します。
Test-Connection www.google.com localhost
$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentArray
飛び散るときは、飛び越した変数を
@
ではなく$
で参照します。 Hashtableを使って感嘆符を使う場合も同じです。
Test-Connection -ComputerName www.google.com -Source localhost
$argumentHash = @{
ComputerName = 'www.google.com'
Source = 'localhost'
}
Test-Connection @argumentHash
Test-Connection www.google.com localhost -Count 1
$argumentHash = @{
Count = 1
}
$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentHash @argumentArray
このように parameters に function を渡すこともできます。
function FunctionName()
{
Param ([string]$ParamName);
#Operations
}