web-dev-qa-db-ja.com

関数をパラメーターとして渡す

他の多くの関数の1つを呼び出す関数「A」を作成しました。書き換え関数「A」を保存するには、関数「A」のパラメーターとして呼び出される関数を渡します。例えば:

function A{
    Param($functionToCall)
    Write-Host "I'm calling : $functionToCall"
}

function B{
    Write-Host "Function B"
}

Function C{
    write-Host "Function C"
}

A -functionToCall C

戻り値:呼び出し中:C

私はそれが戻ることを期待しています:私は呼び出しています:関数C.

私は次のようなさまざまなことを試しました:

Param([scriptblock]$functionToCall)

System.StringをScriptBlockに変換できません

A -functionToCall $function:C

「Write-Host "Function C"」を返します

A - functionToCall (&C)

これは、残りの前に評価します:

 Function C
 I'm Calling :

私はこれがプログラミング101であると確信していますが、正しい構文や、私が間違っていることを解決することはできません。

32
woter324

これはあなたが必要なものですか?

function A{
    Param($functionToCall)
    Write-Host "I'm calling : $functionToCall"

    #access the function-object like this.. Ex. get the value of the StartPosition property
    (Get-Item "function:$functionToCall").ScriptBlock.StartPosition

}

function B{
    Write-Host "Function B"
}

Function C{
    write-Host "Function C"
}


PS> a -functionToCall c

I'm calling : c


Content     : Function C{
                  write-Host "Function C"
              }
Type        : Position
Start       : 307
Length      : 43
StartLine   : 14
StartColumn : 1
EndLine     : 16
EndColumn   : 2
6
Frode F.

これが最高かどうかはわかりませんが、:

function A{
    Param([scriptblock]$FunctionToCall)
    Write-Host "I'm calling $($FunctionToCall.Invoke(4))"
}

function B($x){
    Write-Output "Function B with $x"
}

Function C{
    Param($x)
    Write-Output "Function C with $x"
}

PS C:\WINDOWS\system32> A -FunctionToCall $function:B
I'm calling Function B with 4

PS C:\WINDOWS\system32> A -FunctionToCall $function:C
I'm calling Function C with 4

PS C:\WINDOWS\system32> A -FunctionToCall { Param($x) "Got $x" }
I'm calling Got x
39
Duncan

ScriptBlock をパラメーターとして渡すことを考えましたか?

$scriptBlock = { Write-Host "This is a script block" }
Function f([ScriptBlock]$s) {
  Write-Host "Invoking ScriptBlock: "
  $s.Invoke()
}

PS C:\> f $scriptBlock
Invoking ScriptBlock:
This is a script block
8
Rustam

関数のnamestringとして本当に渡したい場合: &call operator、それを呼び出す:

function A {
  Param($functionToCall)
  # Note the need to enclose a command embedded in a string in $(...)
  Write-Host "I'm calling: $(& $functionToCall)"
}

Function C {
  "Function C"  # Note: Do NOT use Write-Host to output *data*.
}

A -functionToCall C

"..."内で$(...)を使用する必要性については、 この回答 を参照してください。PowerShellの文字列拡張(文字列補間)ルールについて説明しています。

上記の結果はI'm calling: Function Cになります

関数Cimplicit出力(Write-Outputを明示的に使用するのと同じ)を使用して値を返す方法に注意してください。
Write-Hostは、一般的に間違ったツールです 。ただし、PowerShellの出力ストリームをバイパスして、ディスプレイへの書き込みのみを明示的に意図している場合を除きます。

通常、次のシナリオでは&演算子が必要です。

  • 変数参照を介して、および/または名前が一重引用符または二重引用符で囲まれている場合、名前またはパスでコマンドを起動します。

  • scriptブロックを呼び出します

スクリプトブロックは、PowerShellでの周りにコードを渡す好ましい方法です。上記は次のように書き換えることができます(呼び出しメカニズムは変更されず、引数が渡されるだけであることに注意してください)。

function A {
  Param($scriptBlockToCall)
  Write-Host "I'm calling: $(& $scriptBlockToCall)"
}

Function C {
  "Function C"  # Note: Do NOT use Write-Host to output *data*.
}

A -scriptBlockToCall { C }

どちらのシナリオでも、argumentsを渡すには、単に& <commandNameOrScriptBlock>;の後に配置します。 splatting@<var>)を使用して、自動変数$Argsに格納されているバインドされていない引数を渡す方法に注意してください。

function A {
  Param($commandNameOrScriptBlockToCall)
  Write-Host "I'm calling: $(& $commandNameOrScriptBlockToCall @Args)"
}

Function C {
  "Function C with args: $Args"
}


A -commandNameOrScriptBlockToCall C one two # by name
A -commandNameOrScriptBlockToCall { C @Args } one two # by script block

上記はI'm calling: Function C with args: one twoを2回生成します。

4
mklement0

Duncanのソリューションは、私にとって非常に効果的でした。ただし、関数名にダッシュが含まれていると、いくつかの問題が発生します。

私は彼の3番目の例を構築することでそれを回避することができました:

function A{
    Param([scriptblock]$functionToCall)
    Write-Host "I'm calling $($functionToCall.Invoke(4))"
}

function Execute-FunctionWithDash($x)
{
    Write-Output "Function Execute-FunctionWithDash with $x"
}

PS C:\WINDOWS\system32> A -functionToCall { Param($x) Execute-FunctionWithDash $x }
I'm calling Function Execute-FunctionWithDash with 4
3
Derek
    function strdel($a,$b,$c) {
    return ($a.substring(0,$b)+$(substr $a $c $a.length))
}
function substr($a,$b,$c) {
    return $a.substring($b,($c-$b))
}

$string = "Bark in the woods"
$in = $(substr $(strdel $string 0 5) 0 2)
write-Host $in

ここで、関数「substr」は関数「strdel」を$ aパラメーターとして呼び出しました。

https://github.com/brandoncomputer/vds の関数

1

可変数の名前付きパラメーターを渡すため

function L($Lambda){
   write-Host "`nI'm calling $Lambda"
   write-Host "`nWith parameters"; ft -InputObject $Args
   & $Lambda @Args
}

奇妙な関数名でうまく機能するようです

function +Strange-Name($NotUsed,$Named1,$Named2){
   ls -filter $Named1 -Attributes $Named2
}

PS C:\>L +Strange-Name -Named1 *.txt -Named2 Archive

およびexeファイルも

PS C:\>L grep.exe ".*some text.*" *.txt

あなたはまだ注射に注意する必要があるように見えますが

function inject($OrigFunction){
   write-Host 'pre-run injection'
   & $OrigFunction @Args
   write-Host 'post-run injection'
}

PS C:\>L inject +Strange-Name -Named1 *.txt -Named2 Archive
1
Gregor y

どうですか:

function A{
Param($functionToCall)
    $res = Invoke-Command $functionToCall 
    Write-Host "I'm calling : $res"
}

function B{
    "Function B"
}

Function C{
    "Function C"
}

A -functionToCall ${function:C}

$ {function:...}を使用して、関数を値としてパスします。関数を呼び出して、結果を$ resに保存します。

0
Tomer